1、 一个类不能既是final的,又是abstrct的,因为你final类不能有子类,而 abstrct类的声明方法必须在子类中实现。如果final域尚未初始化,就会拒绝编译,必须在类初始化之后或者类的对象完全构造完之后
2、延迟初始化:lazy initialization
3、private和protected访问修饰符只能用于成员,而不能用于类或者接口本身(除非嵌套)
4、构造函数可以有与类成员同样的任何访问修饰符,但构造函数不能是类的成员。
5、类的初始化顺序
执行父类静态代码 执行子类静态代码
初始化父类成员变量(我们常说的赋值语句)
初始化父类构造函数
初始化子类成员变量
初始化子类构造函数
所有类的静态初始化块(从父类自顶向下) -> 所有类的普通初始化块然后接着类的构选器(从父类自顶向下)
如果再实例化一个对象,那么就没有类初始化这个步骤了,因为已经发生在第一次实例化了,类初始化
只会发生一次
!且在
该类的所有对象实例化
之前
6、覆盖方法具有自己的访问说明符。子类可以改变父类方法的访问权限,但只能是提供更多的权限。
覆盖方法还可以改变其他的方法修饰符,synchronized,native,以及strictfp
7、默认情况下认为两个不同的对象不相等,而且它们的散列码通常也不一样。
8、接口方法有隐式的public,不能有其他的访问修饰符。它们也不能够拥有定义实现特征的修饰符——例如native、synchronized或者strictfp,因为它们还没有被实现。它们也不能够是静态的,因为静态犯法不可以是抽象的。
接口所有方法全是抽象方法只能
public abstract修饰
(默认public abstract修饰
),属性默认public static final修饰。
接口是不能实例化的,即不能被分配内存,而static修饰的方法在类实例化之前就已经别分配了内存,这样一来矛盾就出现了:接口不能被分配内存,而static方法必须被分配内存。所以接口中不能有静态的抽象方法。
9、在设计对象创建过程中要调用的方法时尽量避免调用可覆盖的方法——既不是private、static也不是final的方法。
10、当通过对象引用来调用方法时,对象的
真实类将决定使用哪种实现。当访问域时,所用的是引用的
申明类型。在方法内部,对域的引用总是指向
申明该方法的类中所声明的域。如果该类中并未申明相应的域,则会指向继承域。
11、方法隐藏只有一种形式,就是父类和子类存在相同的静态方法。
属性只能被隐藏,不能被覆盖。
隐藏和覆盖的区别:
被隐藏的属性,在子类被强制转换成父类后,访问的是父类中的属性
被覆盖的方法,在子类被强制转换成父类后,调用的还是子类自身的方法
在“静态初始化块”中不能访问“实例属性”
12、
重写 两同两小一大原则
两小:子类方法返回值类型应比父类方法返回值类型更小或相等;(
两者的返回值类型首先必须是一个类层次,再谈大小。返回值类型为基本类型时,父类子类的方法,返回值类型一样
。
父类中的方法返回类型要是子类中重写的那个方法的返回类型的祖先类
)
子类方法声明抛出的异常应比父类方法声明抛出的异常类更小或相等
两同:
方法名相同,参数类型相同
一大
:
子类访问权限大于等于父类方法访问权限。
13、
嵌套类可以访问它的包装类的所有成员,包装类也可以访问其内部类的使用成员,但是只能通过显示地对内部类对象的引用。
内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。
外部类不能直接访问内部类的的成员,但可以通过内部类对象来访问
所以要在static方法(类加载时已经初始化)调用内部类的必须先创建外部类。
外部类的静态方法访问成员内部类,与在外部类外部访问成员内部类一样 静态内部类可以用public,protected,private修饰
14、方法内部类:
把类放在方法内
1 2 3 4 5 6 7 8 | class Outer { public void doSomething(){ class Inner{ public void seeOuter(){ } } } } |
(1)方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
(2
)方法内部类对象不能使用该内部类所在方法的非final局部变量
。
因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。
15、内部类中引用外面的局部变量需要是
fina
l的,
否则就会因为在调用内部类时因为找不到所用的变量而报错!
因为方法内定义的变量是局部变量,离开该方法,变量就失去了作用,也就会自动被消除,而内部类却不会离开它所在方法就失去作用,它有更广的生命周期。
实际做法:
Java编译器的行为是这样的(前提条件是该变量在内部类中被引用):
若定义为final,则java编译器则会在内部类TimerPrint内生成一个外部变量的拷贝,而且可以既可以保证内部类可以引用外部属性,又能保证值的唯一性。
拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变
16、
非
静
态的内部类对象隐式地在外部类中保存了一个引用,指向创建它的外部类对象。
18、
在使用匿名内部类的过程中,我们需要注意如下几点:
1、
使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、
匿名内部类中是不能定义构造函数的。
3、
匿名内部类中不能存在任何的静态成员变量和静态方法。
4、
匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块,
通过
实例初始化块来完成构造器需要完成的事情
。
5、
匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
19、
内部类的继承
内部类的继承,是指内部类被继承,普通类 extents 内部类。而这时候代码上要有点特别处理,具体看以下例子:
- public class InheritInner extends WithInner.Inner {
- // InheritInner() 是不能通过编译的,一定要加上形参
- InheritInner(WithInner wi) {
- wi.super();
- }
- public static void main(String[] args) {
- WithInner wi = new WithInner();
- InheritInner obj = new InheritInner(wi);
- }
- }
- class WithInner {
- class Inner {
- }
- }
可以看到子类的构造函数里面要使用
父类的外部类对象.super()
;而这个对象需要从外面创建并传给形参。
20、用户可以推迟对final域或者局部变量的初始化。这样的final变量被称为空的final。blank final 域必须在初始化块或者构造函数内部初始化,而blank final局部变量必须在使用前进行初始化。
21、十六进制转换为int数 ‘0’48,‘a’97, 'A' 65
static int hexValue(char ch) {
switch (ch) {
case '0':case '1':case '2':
return (ch- '0');
case 'a':case 'b':case 'c':
return (ch- 'a') + 10;
case 'A':case 'B':case 'C':
return (ch- 'A') + 10;
default:
}
return -1;
}
switch表达式必须是char,byte,short,int。jdk1.7 String
22、构造函数不能声明为synchronized的,因为它只在创建对象时执行,而对任何给定的新对象来说,它只能在一个线程中被创建。
23、内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存。即被分配的对象可达但已无用。
内存溢出:指程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。
从定义上可以看出内存泄露是内存溢出的一种诱因,不是唯一因素。
24、new Integer.valueof()返回的是Integer的对象。
Integer.parseInt() 返回的是一个int的值。
new Integer.valueof().intValue();返回的也是一个int的值。
25、类加载:Java命令的作用是启动虚拟机,虚拟机通过输入流,从磁盘上将字节码文件(.class文件)中的内容读入虚拟机,并保存起来的过程就是类加载。
类加载特性 :
*在虚拟机的生命周期中
一个类只被加载一次。
*类加载的原则:延迟加载,能少加载就少加载,因为虚拟机的空间是有限的。
*类加载的时机:
1)第一次创建对象要加载类.
2)调用静态方法时要加载类,访问静态属性时会加载类。
3)加载子类时必定会先加载父类。
4)创建对象引用不加载类.
5) 子类调用父类的静态方法时
(1)当子类没有覆盖父类的静态方法时,只加载父类,不加载子类
(2)当子类有覆盖父类的静态方法时,既加载父类,又加载子类
6)访问静态常量,如果编译器可以计算出常量的值,则不会加载类,例如:public static final int a =123;否则会加载类,例如:public static final int a = math.PI。
27、ArrayList,LinkedList初始化10,扩容位原来1.5倍,即是右移一位加上原始大小
StringBuffer和StringBuilder初始化为16,扩容为2倍+2
StringBuffer在内部维护一个字符数组,当你使用缺省的构造函数来创建StringBuffer对象的时候, StringBuffer的容量被初始化为16个字符,也就是说缺省容量就是16个字符。当StringBuffer达到最大容 量的时候,它会将自身容量增加到当前的2倍再加2,也就是(2*旧值+2)。
StringBuffer str = new StringBuffer();
str.append("大家好我们大家都很愿意学习java语言");
System.out.println("length:"+str.length()); //返回19,因为初始化的16个字符空间已经不够,这时会自动扩容
System.out.println("Capacity:"+str.capacity()); //返回34
Map初始16