继承:就是复用已存在类的方法和域,并能添加一些新的方法和域,满足新的需求;
5.1类、超类和子类
1、在Java中所有的继承都是公有继承
2、在扩展超类定义子类时,仅需指出子类与超类的不同。因此在设计类是应该将通用的方法放在超类中,将特殊用途的方法放在子类中;
3、覆盖:然而,有时超类中的有些方法对于子类并不一定适用,为此需要提供一个新的方法来覆盖超类中的方法;
4、如果超类和子类有相同的方法,那么在子类实例中可以使用关键字super.方法,来表示调用超类方法
5、super不是一个对象的引用,他只是一个指示编译器调用超类方法的特殊关键字
6、在子类中可以增加域、增加方法,或覆盖超类的方法,然而绝对不能删除继承的任何域和方法
7、使用super关键字可以调用父类的构造方法,但是super调用的构造器的语句必须是子类构造器的第一条语句
8、如果子类构造器没有显示的调用超类的构造器,则将自动地调用超类默认的构造器,如果超类没有不带参数的构造器,并在子类的构造器中又没有显示的调用超类的其他构造器,则java编译器报错
9、区别this和super:
this:一是引用隐式参数,二是调用该类的其他构造器
super:一是调用超类的方法,二是超类的构造器
5.1.1继承层次
1、Java不支持多继承
2、继承层次:由一个公共超类派生出来的所有类的集合;
3、继承链:从某个特定的类到其祖先的路径
5.1.2多态
1、多态:一个对象变量可以指示多种实际类型的现象被称为多态,例如可以将子类对向赋给超类变量,也可以赋给原对象变量
2、动态绑定:在运行时能够自动地选择调用那个方法的现象称为动态绑定
特性:无需对现存的代码进行修改就可以对程序进行扩展
3、置换法则(is_a):程序中出现超类对象的任何地方都可以用子对象置换,也就是可以将一个子对象赋给超类变量;
4、注意:不能将一个超类的引用赋给子类变量
5、注意:一旦将子类对象赋值给超类变量,那么子类对象的一切活动都应该服从超类对象的标准
例:前提:Manager是Employee的子类,Manager类中有方法setBonus()
情况一:
Manager boss=new Manager();
Employee []staff=new Employee[3];
staff[0]=boss;
boss.setBonus(5000);//可以
staff[0].setBonus(5000);//不能这样做,因为编译器将staff[0]看成Employee对象
情况二:
Manager boss=new Manager();
Employee e=boss;
e.setBonus();//非法,原因同上
5.1.3动态绑定
1、签名:方法的名字和参数列表,注意返回类型不是签名的一部分
2、允许子类将覆盖方法的返回类型定义为原返回类型的的子类型
3、什么是静态绑定?如果是private方法、static方法、final方法或者构造器,编译器将准确的知道应该调用那个方法,将这种调用方式称为静态绑定。
5.1.4阻止继承:final类和方法
1、不允许扩展(不能被覆盖)的类被称为final类,final类中的所有方法自动地成为final方法,主要的目的是:确保他们不会在子类中改变语义
2、类中的方法(不一定是final类)可以被声明为final,如果这样做,子类就不能覆盖这个方法,
3、final域表示构造对象之后,就不能改变他们的值(只能赋一次值)
4、内联:如果一个方法没有被覆盖并且很短,编译器就能够对他进行优化处理,这个过程称为内联;
5.1.5强制类型转换
1、使用强制类型转换的原因:在暂时忽视对象的实际类型之后,使用对象的全部功能;
2、Java中,每个对象变量都属于一个类型,却切说是一种数据类型
3、强制转换时应注意的事项:
1、只能在继承层次内进行强制转换
2、再将超类转换成子类之前,应该使用instanceof进行检查
3、通过类型转换调整对象类型并不是一种好做法
5.1.6抽象类
1、祖先类更加通用,人们只想它作为派生其他类的基类。而不考虑做为想使用的特定实例,比如说,鸟类,我们知道鸟类会飞(至少打部分会飞),会吃东西,有翅膀,有眼睛,
但谈鸟类时我们并不知道它们怎么飞,用翅膀,还是根本就不会飞,不知道它怎么吃,喙是长是短。只有谈到具体的鸟类时我们才知道,比如燕子,用翅膀飞,黑色羽毛,用
短喙吃,抽象类就是对实例的概括描述,不追究具体细节;
2、用关键字abstract声明抽象类和抽象方法
3、包含一个或多个抽象方法的类本身必须被声明为抽象的abstract
4、抽象类还可以包含具体的数据和具体的方法
5、扩展抽象类的方法:
1、在子类中定义部分的抽象方法或抽象方法也不定义,如果这样子类也必须标记为抽象类
2、在子类中定义父类的全部抽象方法,这样子类就不必标记为抽象类
总结:如果抽象类的子类实现了所有的抽象方法那么子类就不比定义为抽象类,反之就必须定义为抽象的,原因参上第三点
6、不含抽象方法的类也可以被声明为抽象类
7、抽象类不能被实例化,因为即使能实例化,也不能对该对象执行任何操作,应为抽象方法没有方法体,这样是没有意义的
8、可以定义一个抽象类的对象变量,但是它只能引用飞抽象子类的对象
5.1.7受保护访问
1、最好将类中的域标记为private,方法标记为public
2、子类不能访问超类的私有域
3、访问修饰符:
1、private——仅对本类可见
2、public——对所有类可见
3、protected——对本包和所有子类可见
4、默认,不需要任何修饰符——对本包可见
5.2Object:所有类的超类
1、如果没有明确的指出超类,Object就被认为是这个类的超类
2、Object类型的变量只能用于作为各种值得通用持有者
3、在Java中,只有基本类型不是对象
4、所有的数组类型,不管是对象数组还是基本类型的数组都扩展于Object类
5.2.1
5.3泛型数组列表
1、在Java中,允许在运行时确定数组的大小,即可以在[]中用变量;
2、ArrayList类:有点像数组,但在添加或删除元素时,具有自动调节数组容量的功能,且类型参数不准是基本类型;
格式:ArrayList<类型参数> name=new ArrayList<>();Java7中
ArrayList<类型参数> name=new ArrayList<类型参数>()
3、ensureCapacity()方法:如果以经清楚或能够估计出数组的大小,可以在填充前调用该方法
ArrayList<Employee>()=new ArrayList<>(100);
只表示数组列表有保存100元素的潜力,添加的元素超过100,又会重新分配;
4、size方法:返回数组列表中包含实际元素的数目;
5、set方法只能替换数组中已经存在的元素内容;
5.4对象包装器与自动装箱
1、对象包装器类是final的,所以是不可变的,也不能被继承,一旦构造了包装器,就不允许更改包装在其中的值
2、自动装箱:
ArrayList<Interger>() list=new ArrayList<>();
list.add(3);//自动变换成list.add(Integer.valueOf(3));
3自动拆箱:当将一个Integer对象赋值给一个Int时将会自动拆箱;
int n=list.get(i);//int list.get(i).intValue();
4、在算数表达式中也能够自动装箱和拆箱:
Integer n=3;
n++;
5、装箱和拆箱是编译器认可的,而不是虚拟机,虚拟机只是执行这些字节码;
5.5参数数量可变的方法(变参方法)
1、...等同于[]
5.6枚举类
1、在比较两个枚举类型时,永远不需要调用equals,而是直接使用==就可以了
2、在枚举类中可以添加构造器、方法、和域
5.7反射
1、反射:能够分析类能力的程序称为反射
2、class类:在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型信息,这个信息跟踪着每个对象所属的类
。虚拟机利用运行时类型信息选择相应的方法执行,保存这些信息的类称为class
3、一个class对象表示一个特定类的属性
4、注意:一个class对象实际上表示一个类型,而这个类型未必一定是一种类,
例如int不是类,但int.class是一个class类型的对象
5、虚拟机为每个类型管理一个class对象,因此可以利用==实现两个类对象的比较操作
if(e.getClass()==Employee.getClass())