Java核心技术(四):继承

一、类、超类和子类

  • 子类继承父类,二者之间是is-a关系,子类拥有父类的全部资源,并且可以添加特有的域和方法。

  • 子类无法删除。

  • java不支持多继承。

  • 子类可重写父类的方法,注意,重写和方法重载是不同的概念。 在覆盖(重写)一个方法的时候,子类方法不能低于超类方法的可见性。特别是,如果超类方法是 public,子类方法一定要声明为 public。

  • 子类如何调用父类方法:super.父类方法名()。

  • 子类构造器中如何调用父类构造器:super.父类名(参数列表),注意,这句代码必须在子类构造器中的第一句。

如果子类的构造器没有显式地调用超类的构造器,则将自动地调用超类默认(没有参数)的构造器。
如果超类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用超类的其他构造器,则 Java 编译器将报告错误。

  • 多态:一个对象变量可以指示多种实际类型的现象被称为多态。在运行时能够自动地选择调用哪个方法的现象称为动态绑定。

1.多态

  • 在 Java程序设计语言中,对象变量是多态的。一个父类变量既可以引用一个父类对象,也可以引用任何一个子类的对象。
  • 然而,不能将一个父类的引用赋给子类变量。
  • 警告∶ 在 Java中,子类数组的引用可以转换成超类数组的引用,而不需要采用强制类型转换。例如,下面是一个经理数组

2.动态绑定

  前面已经说过了,一个对象变量可以指示多种实际类型的现象被称为多态,在运行时能够自动地选择调用哪个方法的现象称为动态绑定。

  下面请看调用方法的过程:

  • 编译器查看对象的声明类型和方法名。假设调用x.f(param),且隐式参数x声明为C类的对象。需要注意的是∶ 有可能存在多个名字为f,但参数类型不一样的方法。编译器将会一一列举所有C类中名为f的方法和其超类中访问属性为 public 且名为f的方法(超类的私有方法不可访问)。至此,编译器已获得所有可能被调用的候选方法。
  • 重载解析:接下来,编译器将查看调用方法时提供的参数类型。如果在所有名为f的方法中存在一个与提供的参数类型完全匹配,就选择这个方法。这个过程被称为重载解析。由于允许类型转换(int 可以转换成 double,Manager类可以转换成 Employee;类,等等),所以这个过程可能很复杂。如果编译器没有找到与参数类型匹配的方法,或者发现经过类型转换后有多个方法与之匹配,就会报告一个错误。至此,编译器已获得需要调用的方法名字和参数类型。

不过,返回类型不是签名的一部分,因此,在覆盖方法时,一定要保证返回类型的兼容性。允许子类将覆盖方法的返回类型定义为原返回类型的子类型。例如,假设

  • 如果是 private 方法、static方法、final方法或者构造器,那么编译器将可以准确地知道应该调用哪个方法,我们将这种调用方式称为静态绑定。
  • 当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类的方法。否则,将在D类的超类中寻找该方法,以此类推。

  每次调用方法都要进行搜索,时间开销相当大。因此,虚拟机预先为每个类创建了一个方法表,其中列出了所有方法的签名和实际调用的方法。

  这里需要提醒一点,如果调用super.f(param),编译器将对隐式参数超类的方法表进行搜索。

3.阻止继承:final类和方法

  用 final修饰的类是禁止继承的;用final修饰的方法,则表明该方法不允许类的子类重写;final类中的所有方法默认为是final方法。

  在早期的Java中,有些程序员为了避免动态绑定带来的系统开销而使用final关健字。如果一个方法没有被覆盖并且很短,编译器就能够对它进行优化处理,这个过程为称为内联。例如,内联调用e.getName()将被替换为访问e.name域。然而,如果getName()在另外一个类中被覆盖,那么编译器就无法知道覆盖的代码将会做什么操作,因此也就不能对它进行内联处理了。

  幸运的是,虚拟机中的即时编译器比传统编译器的处理能力强得多。这种编译器可以准确地知道类之间的继承关系,并能够检测岀类中是否真正地存在覆盖给定的方法。如果方法很简短、被频繁调用且没有真正地被覆盖,那么即时编译器就会将这个方法进行内联处理。如果虚拟机加载了另外一个子类,而在这个子类中包含了对内联方法的覆盖,那么将会发生什么情况呢?优化器将取消对覆盖方法的内联。这个过程很慢,但却很少发生。

4.抽象类

  为了提高程序的清晰度,包含一个或多个抽象方法的类本身必须被声明为抽象的。

abstract class Person{
    
    
	……
	public abstract String getDescription();
}

  • 除了抽象方法之外,抽象类还可以包含具体数据和具体方法。但尽量使得抽象类中不包含具体方法。
  • 抽象方法充当着占位的角色,它们的具体实现在子类中。不过,在子类中定义部分抽象方法或抽象方法也可以不定义,这样就必须将子类也标记为抽象类。
  • 类即使不含抽象方法,也可以将类声明为抽象类。
  • 抽象类不能被实例化;可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。

5.访问修饰符总结

  • 对本类可见private
  • 对所有类可见public
  • 对本包和所有子类可见protected
  • 默认本包可见

二、Object类:所有类的父类

  可以使用Object类型的变量引用任何类型的对象。

1.equals方法

  检测一个对象和另一个对象是否相等,用于判断两个对象是否具有相同的引用。

  在子类中定义 equals 方法时,首先调用超类的 equals。如果检测失败,对象就不可能相等。如果超类中的域都相等,就需要比较子类中的实例域。

  Java中的equals方法具有以下特性:

  • 自反性∶ 对于任何非空引用x,x.equals(x)应该返回 true。
  • 对称性∶ 对于任何引用x和y,当且仅当yequals(x)返回true,x.equals(y)也应该返回 true。如果x和y不属于同个类,可能不适用。
  • 传递性∶对于任何引用x、y和z,如果x.cquals(y)返回true,yequals(z)返回true, x.equals(z)也应该返回 true。
  • 一致性∶如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果。
  • 对于任意非空引用x,x.equals(null)应该返回 false。

2.hashcode方法

散列码是由对象导出的一个整型值。散列码是没有规律的。如果x和y是两个不同的对象,x.hashCode()与y.hashCode()基本上不会相同。在表5-1中列出了几个通

3.toString方法

三、对象包装器与自动装箱

  • 对象包装器:

  所有的基本类型都有一个与之对应的类。这些类称为包装器∶Integer、Long、Float、Double、Short、Byte、Character、Void和 Boolean(前 6个类派生于公共的超类 Number)。对象包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,对象包装器类还是 final,因此不能定义它们的子类。

  泛型是能是引用类型而不能是基本类型。

  • 自动装箱:

  list是一个集合对象,list.add(3)将自动地变换成list.add(Integer.valueOf(3)。这一过程就是自动装箱。
  int n= list.get(i)将自动被翻译成int n=list.get(i).intValue()。这一过程就是自动拆箱。

  最后强调一下,装箱和拆箱是编译器认可的,而不是虚拟机。编译器在生成类的字节码时,插入必要的方法调用。虚拟机只是执行这些字节码。

四、反射

1.Class类

在程序运行期间,保存对象的运行时类型信息的类被称为 Class。

	Employee e;
	……
	Class c1=e.getClass();//获取Class对象
	String classType=c1.getName();//获取e的类名,包含了包前缀
	String name=e.getName();//获取e的对象名
	Class c2=Class.forName(classType);//也可通过已知的类名获取Class对象
	Class c3=Date.class;//也可通过这种方式获取类对象
	Class c4=int.class;
	CLass c5=Double[].class;
	Object o=e.getClass().new Instance();//创建一个和e同类型的实例,调用的是默认构造器


2.捕获异常

	try
	{
    
    
		//可能抛出异常的语句
	}
	catch(Exception e)
	{
    
    
		//处理器语句
	}

  一旦try中出现异常,将跳过剩余的部分,直接进入catch中进行处理;若try中没有出现异常,则跳过catch中的部分。

3.利用反射分析类的能力

  说白了就是通过调用Class类中的方法得到关于所涉及对象的域、方法、构造器、访问权限修饰符相关的信息,这部分学习下Java API中有关Class的部分就好。

4.在运行时使用反射分析对象

  在代码运行时获取到对象的状态等。好好看看API。

猜你喜欢

转载自blog.csdn.net/Tracycoder/article/details/112308310