类、超类和子类
1.关键字 extends 表示继承。Java中所有的继承都是公有继承,extends 表明正在构造的新类派生于一个已存在的类。已存在的类称为超类(superclass)、基类(base class)或父类(parent class),新类称为子类(subclass)、派生类(derived class)或孩子类(child class)。
2.如需再子类中调用超类中同名的方法,则可以使用特定关键字super实现调用。注:super与this不是类似的概念,super不是一个对象的引用,不能将super赋给另一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字。this:一引用隐式参数,二调用该类的其他构造器。super:一调用超类的方法,二调用超类的构造器。
3.一个对象变量可以指示多种实际类型的现象称为多态,在运行时能够自动地选择调用哪个方法的现象称为动态绑定。
4.由一个公共超类派生出来的所有类的集合被称为继承层次,其中,从某个特定的类到其祖先的路径被称为该类的继承链。
5.“is—a” 规则(置换法则)
6.调用对象方法的执行过程:
- 编译器查看对象的声明类型和方法名。
- 编译器将查看调用方法时提供的参数类型。
- 如果是private方法,static方法,final方法或者构造器,那么编译器将可以准确地知道应该调用哪个方法,我们将这种调用方式称为静态绑定。
- 当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类的方法。
7.动态绑定有一个非常重要的特征:无需对现存的代码进行修改,就可以对程序进行扩展。!在覆盖一个方法时。子类方法不能低于超类方法的可见性。特别是,如果超类方法时public,子类方法一定要声明为public。
8.阻止继承:final类和方法
9.强制类型转换。有时候可能需要将某个类的对象引用转换成另外一个类的对象引用。转换语法与数值表达式的类型转换类似,仅需要一对圆括号将目标类名括起来,并放置在需要转换的对象引用之前。注:只能在继承层次内进行类型转换;在将超类转换成子类之前,应该使用instanceof进行检查。
10.abstract关键字,抽象类,不能被实例化。
11.受保护访问protected。
Object:所有类的超类
可以用object类型的变量引用任何类型的对象。
在Java中,只有基本类型不是对象,例如数值、字符和布尔类型的值都不是对象。所有的数组类型,不管是对象数组还是基本类型数组都扩展于Object类。
1.equals方法
2.相等测试与继承
Java 语言规范要求equals方法有以下特性:自反性;对称性;传递性;一致性;对于任意非空引用x,x.equals(null)应返回false。
注:如子类能够拥有自己的相等概念,则对称性需求将强制采用getclass进行检测。如由超类决定相等的概念,那么可用instanceof进行检测,这样可以在不同子类的对象之间进行相等的比较。
3.hashcode方法。散列码是由对象导出的一个整型值。
4.toString方法。返回表示对象值的字符串。
泛型数组列表
- ArrayList类,使用起来有点像数组,但在添加或删除元素时,具有自动调节数组容量的功能,而不需要为此编写任何代码。
- add方法可以将元素添加到数组列表中。
- 如事先明确数组可能存储的元素数量,可以在填充数组之前调用ensureCapacity方法。
!数组列表的容量与数组大小有一个重要区别。如为数组分配100个元素的存储空间,数组就有100个空位置可以使用。而容量为100个元素的数组列表只是拥有保存100个元素的潜力(实际上,重新分配空间的话,将会超过100),但在最初,甚至完成初始化构造之后,数组列表根本不含有任何元素。
1.访问数组列表元素。使用get 和 set 方法实现访问或改变数组元素的操作。
2.类型化与原始数组列表的兼容性。
对象包装器与自动装箱/拆箱
对象包装器类:Integer、Long、Float、Double、Short、Byte、Character、Void 和 Boolean 不可变&不能定义子类。!不能使用包装器类创建修改数值参数的方法。基本类型的值不是对象,可以使用JavaAPI中的包装类包装成对象。
参数数量可变的方法
例:printf
枚举类
比较两个枚举类型的值时,永远不需要调用equals,直接用“==”就可以。每个枚举类都有一个静态的values方法,它将返回一个包含全部枚举值的数组。
反射
反射机制可以用来:在运行中分析类的能力;在运行中查看对象;实现通用的数组操作代码;利用Method对象,此对象很像c++中的函数指针。
1.class类
- getClass()方法:返回一个Class类型的实例。
- forName()方法:获得类名对应的Class对象。
- newInstance()方法:快速创建一个类的实例。
2.捕获异常
两种异常类型:未检查异常和已检查异常,提供处理器对异常情况进行处理。
3.利用反射分析类的能力
反射机制最重要的内容——检查类的结构
在java.lang.reflect包中有三个类Field、Method 和 Constructor 分别用于描述类的域、方法和构造器。
4.在运行时使用反射分析对象
5.使用反射编写泛型数组代码
Array 类中的静态方法newInstance,能够构造新数组,调用时必须提供两个参数:数组的元素类型&数组长度
6.调用任意方法
Method 类中 invoke 方法,允许调用包装在当前Method 对象中的方法,其参数和返回值必须是Object 类型的。可以使用Method 对象实现c(或c#中发的委派)语言中函数指针的所有操作。
继承设计的技巧
- 将公共操作或域放在超类
- 不要使用受保护的域
- 使用继承实现“is—a”关系
- 除非所有继承的方法都有意义,否则不要使用继承
- 在覆盖方法时,不要改变预期的行为
- 使用多态,而非类型信息
- 不要过多的使用反射
例
/**
* 继承demo,英雄-父类
* @author 棣哩哩
* @date 2018年12月10日 下午4:37:38
* @remarks TODO
*/
public class Hero {
private String nickName;
private int level;
private int maxLife;
private int currLife;
public Hero() {
System.out.println("父类默认构造!");
}
public Hero(String nickName, int level, int maxLife, int currLife) {
super();
this.nickName = nickName;
this.level = level;
this.maxLife = maxLife;
this.currLife = currLife;
}
public void move(){
System.out.println("Hero类的move方法");
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getMaxLife() {
return maxLife;
}
public void setMaxLife(int maxLife) {
this.maxLife = maxLife;
}
public int getCurrLife() {
return currLife;
}
public void setCurrLife(int currLife) {
this.currLife = currLife;
}
}
/**
* 战士类-继承了Hero类
* @author 棣哩哩
* @date 2018年12月10日 下午4:43:18
* @remarks TODO
*/
public class Warrior extends Hero{
/** 战士特有属性,物理攻击*/
private int physicalAttack;
public Warrior(){
//super(); //子类构造中,默认就会调用父类构造
System.out.println("子类默认构造");
}
public Warrior(String nickName,int physicalAttack){
setNickName(nickName);
setPhysicalAttack(physicalAttack);
}
public int getPhysicalAttack() {
return physicalAttack;
}
public void setPhysicalAttack(int physicalAttack) {
this.physicalAttack = physicalAttack;
}
}
public class HeroTest {
public static void main(String[] args) {
Warrior 韩信 = new Warrior();
}
}