天天看点

java编程思想读书笔记(2)

1、调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。

2、如果父类有带有参数的构造方法,那么在子类构造方法中必须用super关键字显式调用,不然编译器就会报告自己找不到默认形式的一个构建器。

3、当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中。这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值。 当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。修饰方法时不可继承。

4、static final用来修饰成员变量和成员方法,可简单理解为“全局常量”! 对于变量,表示一旦给值就不可修改,并且通过类名可以访问。 对于方法,表示不可覆盖,并且可以通过类名直接访问。final修饰的方法能去除动态绑定的过程,不需要去找其父类或子类是否有这个方法,能提高执行效率。

5、关于初始化顺序,自己写了以下代码来总结了下:

public class People {
	public static String i1 = getStr();
	
	public static String getStr(){
		System.out.println("people 静态常量");
		return "success";
	}
	
	static {
		System.out.println("people 静态初始化块");
	}
	
	{
		System.out.println("people 初始化块");
	}
	
	public People(){
		System.out.println("people 构造方法");
	}
}
           
public class Man extends People{
   public static String i1 = getStr();
	
	public static String getStr(){
		System.out.println("man 静态常量");
		return "success";
	}
		
	static {
		System.out.println("man 静态初始化块");
	}
	
	{
		System.out.println("man 初始化块");
	}
	
	public Man(){
		System.out.println("man 构造方法");
	}
	
	
	public static void main(String[] args) {
		new Man();
	}
}
           

以上的执行结果是:

people 静态常量
people 静态初始化块
man 静态常量
man 静态初始化块
people 初始化块
people 构造方法
man 初始化块
man 构造方法
           

当java虚拟机调用Man类的main方法时,Man类代码在首次使用的时候载入,此时会发现其有父类,所以先载入了people,由于此时未创建对象,所以出现了以上结果。

6、所有的Java虚拟机实现必须在每个类或接口首次主动使用时初始化。,以下6种情况符合主动使用的要求:    

  • 当创建某个类的新实例时(new;或者不明确的创建。反射。克隆或者反序列化)
  • 调用某个类的静态方法 
  • 使用某个类或接口的静态字段,或者对该字段赋值(final修饰的除外,它被初始化为一个编译时的常量表达式)  
  • 调用Java API中的某些反射方法  
  • 当初始化某个类的子类时(要求超类也已经初始化) 
  •  当虚拟机启动时某个被表明为启动类的类(main()方法那个类)

7、Java的动态绑定又称为运行时绑定。意思就是说,程序会在运行的时候自动选择调用哪儿个方法。

public class Son extends Father
 	Son son = new Son();
 	son.method();
           

  1. 首先,编译器根据对象的声明类型和方法名,搜索相应类(Son)及其父类(Father)的“方法表”,找出所有访问属性为public的method方法。

    可能存在多个方法名为method的方法,只是参数类型或数量不同。

  2. 然后,根据方法的“签名”找出完全匹配的方法。

    方法的名称和参数列表称为方法的签名。

    在Java SE 5.0 以前的版本中,覆盖父类的方法时,要求返回类型必须是一样的。现在子类覆盖父类的方法时,允许其返回类型定义为原始类型的子型。

     3. 如果是private、static、final 方法或者是构造器,则编译器明确地知道要调用哪儿个方法,这种调用方式成为“静态调用”。

  4. 调用方法。

    如果子类Son中定义了 method() 的方法,则直接调用子类中的相应方法;如果子类Son中没有定义相应的方法,则到其父类中寻找method()方法。

8、接口也包含了基本数据类型的数据成员,但它们都默认为static和final。接口只提供一种形式,并不提供实施的细节。项目中一些数据容器就使用接口来存储。在实现一个接口的时候,来自接口的方法必须定义成public。否则的话,它们会默认为“友好的”,而且会限制我们在继承过程中对一个方法的访问——Java编译器不允许我们那样做。

9、根据Java命名规则,拥有固定标识符的static final基本数据类型(亦即编译期常数)都全部采用大写字母(用下划线分隔单个标识符里的多个单词)。

10、接口中定义的字段会自动具有static和final属性。它们不能是“空白final”,但可初始化成非常数表达式。改表达式会在编译时自动计算。字段并不是接口的一部分,而是保存于那个接口的static存储区域中。

 如:int rint = (int)(Math.random() * 10);

11、普通(非内部)类不可设为private或protected——只允许public或者“友好的”。但是内部类可以。

12、部类必须拥有对封装类的特定对象的一个引用,而封装类的作用就是创建这个内部类。随后,当我们引用封装类的一个成员时,就利用那个(隐藏)的引用来选择那个成员。除非已拥有外部类的一个对象,否则不可能创建内部类的一个对象。这是由于内部类的对象已同创建它的外部类的对象“默默”地连接到一起。然而,如果生成一个static内部类,就不需要指向外部类对象的一个句柄.

内部类为static时:

Mytest.A1 a = new Mytest.A1();

不为static时:

Mytest  my = new Mytest();

Mytest.A1 a = my.new  A1();