第1章 对象导论
计算机是头脑延伸的工具。
所有编程语言都提供抽象机制。
每个对象看起来都有点像一台微型计算机。
每个对象在内存中都有一个唯一的地址。
每个对象都有一个接口。
向对象发送消息。
每个对象都提供服务。
每个对象都可以很好地完成一项任务,但是它并不试图做更多的事。
public 任何人都是可用的。
private 除类型创建者和类型的内部方法之外的任何人都不能访问。
protected 与private作用相当,差别仅在于继承的类可以访问protected成员。
Java的默认访问权限:包访问权限,类可以访问在同一个包中的其他类的成员。
代码复用是面向对象程序设计语言所提供的最了不起的优点之一,复用某个类的最简单方式就是直接使用该类的一个对象。
在建立新类时,应该首先考虑组合(将一个类的对象置于新类中),而不是盲目的继承。
类与基类具有相同的类型。
通过继承而产生的类型等价性是理解面向对象程序设计方法内涵的重要门槛。
Java以extends关键字表示继承。
把一个对象不当做它所属的特定类型来看待,而是将其当做其基类的对象来对待。这样的代码不会受添加新类型的影响的。
通过导出新的子类型而轻松扩展设计的能力是对改进进行封装的基本方式之一。
编译器不可能产生传统意义上的函数调用。
在OOP中,程序直到运行时才能够确定代码的地址,这叫做后期绑定,运行前并不知道将被执行的确切代码。而前期绑定是指编译器将产生对一个具体函数名字的调用,运行时将这个调用解析到将要被执行的代码的绝对地址。
在Java中,后期动态绑定是默认行为,不需要添加额外的关键字来实现多态。
向上转型奠定了多态的基础。
Java中所有的类都继承自Object,因此不会因无法确定对象的类型而陷入僵局,使垃圾回收器的实现变得更容易,对系统级操作(如异常处理)显得尤其重要,并且给编程带来了更大的灵活性。
ArrayList 随机访问
LinkedList 插入
参数化类型,在Java中称为范型。一对尖括号,中间包含类型信息,通过这些特征就可以识别对范型的使用。范型实现了向下转型。
在堆栈中创建存储空间和释放存储空间通常各需要一条汇编指令即可,分别对应将栈顶指针向下移动和将栈顶指针向上移动。
对于允许在堆栈中创建对象的语言,编译器可以确定对象存活的时间,并可以自动销毁它。
Java一开始就内置了异常处理,而且强制你必须使用它,否则编译时就会报错。
异常处理在面向对象语言出现之前就已经存在了。
applet是只在Web浏览器中运行的小程序,Java applet始终没有得到大规模应用。
servlet实现服务端编程。
对于设计良好的程序,通过阅读它就可以很容易地理解其代码。
我特别推荐读者看看Python。
第2章 一切都是对象
Java中(几乎)一切都是对象。
String s; 创建的是一个String类型的引用,而不是一个对象。
new关键字的意思是“给我一个新对象”。
5个地方可以存储数据:寄存器、堆栈、堆、常量存储、非RAM存储。
堆用于存放所有的Java对象。
常量值通常直接存放在程序代码内部。
Java系统必须知道存储在堆栈内所有项的确切生命周期;编译器不需要知道存储的数据在堆里存活多长时间。
基本类型不是用new来创建的,而是一个并非是引用的“自动”变量,直接存储“值”,置于堆栈中。基本类型具有的包装器类,使得可以在堆中创建一个非基本对象。
char c = 'x'; // 堆栈 Character ch = new Character('x'); // 堆
所有数值类型都有正负号。
Java数组的范围检查,是以少量的内存开销及运行时的下标检查为代价的。
一旦看到null关键字,Java就知道这个引用还没有指向某个对象。
一般数组会初始化为null,若是基本类型,则会将这种数组所占的内存全部置零。
Java不允许变量重复定义
{ int x = 12; { int x = 96; // Illegal } }
Java对象不具备和基本类型一样的生命周期。超出作用域,消失的是引用,对象本身仍占据内存空间,由垃圾回收器来处理。
如果类的字段是对某个对象的引用,那么必须初始化该引用,以便使其与一个实际的对象相关联;若是基本类型,即使没有初始化,Java也会确保它获得一个默认值。
当变量作为类的成员时,Java才确保给定其默认值;否则,变量得到的可能是任意值,而不会被自动初始化为零,这种情况下若没有手动初始化,Java会直接视为编译错误,6不6。
面向对象的程序设计通常简单地归纳为“向对象发送消息”。
程序似乎只是一系列带有方法的对象组合。
Java通过域名反转来解决名字重复的问题,这就是Java的魅力之一:这种机制意味着所有的文件都能够自动存活于它们自己的名字空间内,而且同一个文件内的每个类都有唯一的标识符。
Java消除了所谓的“向前引用”的问题。
Java中所有的代码都必须写在类里。
除非用new创建那个类的对象,否则,实际上并未获得任何对象。
即使从未创建某个类的任何对象,也可以调用其static方法或访问其static域,也就是类数据/类方法。
类方法只是函数,不会分配存储空间。
static方法常常拿来做“牧羊人”的角色,负责看护与其隶属同一类型的实例群。
java.lang会自动被导入到每一个Java文件中。
不知道类属于哪个类库,可以在官网查JDK文档。
Java编译器要求main方法必须要有args,是因为args要用来存储命令行参数。
Java最强大的优势之一就是它具有庞大的标准类库集。
编译和运行
javac HelloDate.java java HelloDate
- /*和*/之间的所有东西都会被忽略。
- javadoc是用于提取注释的工具,它是JDK安装的一部分。用/** */表示。
- 编写"doclets"可以对javadoc处理过的信息执行特殊的操作(例如,产生不同格式的输出)
- 编写“doclets”可以对javadoc处理过的信息执行特殊的操作(例如,产生不同格式的输出)
- 在java.sun.com的JDK文档中,查阅“tooldocs”,了解javadoc更多信息。
javadoc只对public和protected起效,private会忽略掉。
第3章 操作符
"+"字符串拼接,也会字符串转换。如果String类型+非String类型,会尝试转换为String类型。
赋值,基本类型是copy,对象是引用。
为对象赋值,可能会产生意想不到的结果。
同样的,对象在类方法传参时,也是引用,也会意想不到。
Random对象的种子,用于随机数生成器的初始化值,随机数生成器对于特定的种子值总是产生相同的随机数序列。
用括号提升阅读性
x = a * (-b)
一元加号唯一的作用仅仅是将较小类型的操作数提升为int。
Java=C++--。
基本类型用==或!=,内置类用equals,自定义类覆盖equals()方法。
逻辑运算符 && || ! 只可应用于布尔值。
二进制没有直接常量表示方法,可以使用Integer和Long类的静态方法toBinaryString()实现。
编译器通常会将指数当做double,所以
float f4 = 1e-43
,会有出错提升,告诉我们必须使用类型转换将double转为float,可以在后面加个f,指示为float,float f4 = 1e-43f
。boolean-exp ? value0 : value1,可能引起可读性变差,需谨慎使用。
int x = 0, y = 1; System.out.println("" + (x + y)) // 添加括号,保证先求和,而非转换为String
"" + int
比Integer.toString()好用。窄化转换(如long转int)可能出现信息丢失,所以必须显示转换。扩展转换则不必。
第4章 控制执行流程
- Java不允许将一个数字作为布尔值使用。
- Java里唯一用到逗号操作符的地方就是for循环的控制表达式。
for(int i = 1, j = i + 1;i < 5; i++, j = i * 2)
这里的多个初始化变量必须具有相同的类型。- 只要有可能,就使用foreach。
- 编译器将while(true)和for(;;)看作一回事。
- Java没有goto。
- 在Java里需要使用标签的唯一理由就是因为有循环嵌套存在,而且想从多层嵌套中break或continue。
- switch的选择因子必须是int或char。
- Java里面也有单引号,即char,如
char x = 'a';
。
第5章 初始化与清理
构造器没有返回值,这与返回值为空(void)明显不同。
为啥不能通过返回值来区分重载方法?因为
f();
这样调用就懵逼了。在同一个类中,方法a调方法b,不需要this关键字。不像python必须用self才能调。这一点上Java反而比python更简洁了。哈哈,有点讽刺。
要想通过this在一个构造器中,调用另外一个构造器,需要1调用代码置于最起始处 2只能调一个不能调两个。
static方法就是没有this的方法。static方法的主要用途是通过类本身来调用static方法。相当于python的classmethod。不过Java中的static方法不能直接调用非静态方法,只能通过对象引用间接去调。记住!static方法是没有this关键字的方法!
关于垃圾回收的2点须知:1.对象可能不被垃圾回收。2.垃圾回收并不等于“析构”。
finalize()
不一定会被执行。因为对象可能不被垃圾回收,就有可能不执行finalize()
。保险方法是自己创建一个执行清理工作的普通方法。使用垃圾回收器的唯一原因是为了回收程序不再使用的内存。
那
finalize()
有什么作用?它的作用很特殊,垃圾回收器是不会回收通过某种创建对象方式以外的方式为对象分配的存储空间。比如调用C语言的malloc()
函数,就需要在finalize()
中调用free()
函数来清理。Java不允许创建局部对象,必须使用new创建对象。
垃圾回收器的存在并不能完全代替析构函数。
如果JVM并未面临内存耗尽的情形,它是不会浪费时间去进行垃圾回收以恢复内存的。
System.gc(); // Force garbage collection & finalization
垃圾回收器对于提高对象的创建速度,具有明显的效果。这就是某些JVM的工作方式。存储空间的释放会影响存储空间的分配。
通过垃圾回收器对对象重新排列,实现了一种高速的、有无限空间可供分配的堆模型。
“自适应的、分代的、停止-复制、标记-清扫”式垃圾回收器。
JVM在代码每次被执行的时候都会做一些优化,所以执行的次数越多,它的速度就越快。
无法阻止自动初始化的进行,它将在构造器被调用之前发生。
int i = 7;
这里的i
会先被置0,然后变成7。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。包括构造器哦!
static
还有一个重要知识点,就是,静态数据都只占用同一份存储区域。这就决定了static
是不能在方法中定义的,必须在类里面定义。新手很可能会在main()
里面定义static
,编译会报错的。构造器可以看成静态方法。
静态初始化只在Class对象(一个特殊的对象)首次加载的时候进行一次。
引用的初始化值是null。
main方法可以通过
ClassName.main()
来调用。如果没有定义
toString()
,默认打印类的名字和对象的地址,如A@1a46e30
。自动包装机制,如int自动包装为Integer。
注释标签。
// {CompileTimeError} (Won't compile)
。你应该总是只在重载方法的一个版本上使用可变参数列表,或者压根就不是用它。
把enum当做类来使用就完事了
public enum Spiciness { NOT, MILD, MEDIUM, HOT, FLAMING }
第6章 访问权限控制
- 每个编译单元只能有一个public类,否则编译器就不会接受。
- CLASSPATH包含一个或多个目录,用作查找.class文件的根目录。
- CLASSPATH帮助import找到相应文件。
- 在使用了有冲突名字的情况下,必须指定全名。
- 条件编译。
- 报错找不到类时,注释掉
package
语句,你就可以知道问题出在哪里了。 - 骚操作,把构造器修饰为private,就只能通过指定方法创建对象了。
- 类既不可以是private,也不可以是protected。只能是包访问权限或public。
- 相同目录下的所有不具有明确package声明的文件,都被视作是该目录下默认包的一部分。
版权申明:本文为博主原创文章,转载请保留原文链接及作者。
来源:https://www.cnblogs.com/df888/p/12495933.html