+ 超类不是超级类,指的是父类,基类,是一个更加广泛、更加普遍适用的类。而子类则是超类的子集,是“更具个性化的”、功能更加细致和丰富的类。公共方法应该放在超类中,而特殊方法应该放在子类中
+ `注意:在构造器中的this(...)和super(...)的具体含义是调用自身的另一个构造器/调用超类的构造器,都只能在构造器的第一条语句中出现`
+ 可以将一个子类的引用赋给超类变量。因为这样只会新增一些方法和域,超类的方法一定会出现在子类中。而不能将一个超类的引用赋给子类变量。因为如果这么做的话,会导致子类中特有的一些方法和域丢失,进而导致在方法调用的时候出现运行时错误
+ 如果将一个类声明为final,只有其中的方法自动成为final,而不包括域
+ 在将超类`强制转换`成子类时,应该使用instanceof进行检查,以防产生ClassCastException异常。而一般情况建议减少类型转换和instanceof
+ `注意:与C++不同,protected对子类以及同一个包中的所有其他类都可见,而不是只对子类可见`
+ Object.equals()比较两个对象`是否具有相同引用`,如果需要其他的相等方法,则需要重写equals方法
+ 字符串的散列码(hashCode)是由字符串导出的
+ ArrayList.ensureCapacity(int n)或new ArrayList(int n)可以扩充列表底层数组的值。具体见[ArrayList中ensureCapacity的使用与优化](https://blog.csdn.net/nzh1234/article/details/22752095)。与数组new int[100]不同,数组新建是有100个空位置可以使用,而链表只是有保存100个元素的潜力。
+ ArrayList.trimToSize(int n)将存储区域的大小调整为当前元素所需要的存储空间数目,多余空间被GC回收
+ ArrayList的下标也是从0开始
+ ArrayList不允许是基本类型,但是可以是基本类型的包装器
+ 基本类型的包装器具有自动装箱和拆箱功能。所以对于包装器,可以采取与基本类型类似的运算方法,包括=、+、-、*、/
+ 包装类的数值是不可以改变的,与String相同。用=重新赋值会更改指向包装类的引用,使其指向新的包装类
+ 关于String s = new String("a"):至少创建一个对象,至多创建两个对象。首先在string池中搜索"a"字符串是否存在,不存在则创建,存在则将它的引用赋值给s;遇到new,创建新对象,并将引用赋给s
+ 包装器的==为比较引用(所有非基本类型都是如此)。如果要比较值相等,使用equals()
+ 自动装箱规范要求boolean/byte/char≤127、介于-128~127的short和int被包装到固定的对象中。也就是说如果符合上述条件,相同数值的包装器实例使用==比较结果一定为真
+ 参数数量可变:在方法定义中,参数中形如Object...中的省略号表示可以接受任意数量的对象
## 枚举类
例子:
```java
public enum Size{ SMALL, MEDIUM, LARGE, EXTRA_LARGE };
```
实际上,这个声明定义的类型是一个类,它刚好有四个实例,在此尽量不要构造新对象。
因此,在比较两个枚举类型的值时,永远不需要调用equals方法,而直接使用"=="就可以了。(equals()方法也是直接使用 ==, 两者是一样的效果)
如果有需要,可以在枚举类中添加方法
```java
public enum Mode {
PULLDOWN("下拉"), PULLUP("上拉");
private final String value;
Size(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
```
以上图为例。在初始化此枚举类型时,将会自动使用类的构造器(只能为private)构造两个实例,并且在整个生命周期,也只有这两个实例。并且在其他代码内,不能创建enum实例。
ordinal方法返回enum声明中枚举常量的位置,位置从0开始。
## 反射
反射的功能极其强大,他可以用来:
+ 在运行时分析类的能力
+ 在运行时查看对象,例如,编写一个toString方法供所有类使用
+ 实现通用的数组代码
+ 利用Method对象,这个对象很像C++中的函数指针
### Class类
Java运行时为每个对象维护一个被称为运行时的类型标识,这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。
Class类就是专门访问这些信息的类。Object.getClass将会返回一个Class实例。
+ Class.getName() 获取类的名字,包名也包含其中
+ Class.forName() 静态方法,获取类名对应的Class对象
+ Class.newInstance() 可以动态创建一个实例。`注意:创建的实例所对应的类一定要有无参构造器才可以调用newInstance()(自定义的有参构造器会覆盖无参构造器,如果有有参构造器存在,务必要重写一个无参构造器),否则会报实例化异常InstantiationException`
JVM为每个类型管理一个Class对象。因此,可以利用 == 运算符实现两个类对象比较。if(e.getClass() == Employee.class)注意两个返回的都是一个Class对象
Class类中
+ Field[] getFields()
+ Method[] getMethods()
+ Constructor[] getCOnstructors()
只会返回这个类或者其超类的公有部分(域、方法、构造器)
若想获得所有部分(域、方法、构造器),使用形如getDeclaredFields()的函数
在Field/Method/Constructor中,getModifiers()返回一个描述构造器、方法或域的修饰符的整形数值。可以调用Modifier类中的静态方法去判断修饰符的情况。例如:Modifier.isPrivate(con.getModifiers())
为了安全,反射对对象的值的访问默认也受权限修饰符的制约。Java安全机制在默认情况只允许任意对象有哪些域,而不能读出不具有读取权限的域的值。
然而,可以通过setAccessible()来修改上述对象的访问控制
【笔记】《Java核心技术 卷I》 第五章 继承