1、继承:extends
calss Manager extends Employee
{
添加方法或域
}
说明:Manager 类 继承于 Employee 类,Employee 称为:超类、基类、父类;新类称为:子类、派生类、孩子类。
继承的好处:子类可以使用父类的方法和域(属性)
如何使用父类的方法:super.getName()、super不是一个对象的引用,只是一个指示编译器调用超类方法的特殊关键字。子类不可以删除继承的任何域和方法
关于构造器:也可以使用 super 调用超类的构造器
2、关于多态:一个对象变量可以指示多种实际类型的现象被称为多态,在运行时能够自动地选择调用哪个方法的现象称为动态绑定。(比如 子类对象在调用使用时能区分调用的是子类还是父类的方法!)
3、继承层次:继承可以是多层次的,由一个公共超类派生出来的所有类的集合被称为继承层次,在继承层次中,从某个特定的类到其祖先的路径被称为该类的继承链。Java不支持多继承(子类同时继承多个超类)
4、多态详解:
判定继承的简单规则就是“包含”,“水果”包括“苹果”,所以水果是苹果的超类,反之并不是所有水果都是苹果。
“包含”的另一种表示方法是“置换法则”,他表明程序中出现超类对象的任何地方都可以用子类对象置换。
对象变量是多态的,超类对象可能是自己本身的引用,也可能是其子类任何对象的引用!!
子类对象可以直接转化为超类对象(不需要强转,就像苹果对象转为水果对象,苹果肯定具有水果的特点:域和方法)
5、动态绑定
方法调用的执行过程:
a 编译器查看对象的声明类型和方法名(同名的方法,超类和本类的,public的)
b 编译器将查看调用方法时提供的参数类型,如果参数类型完全匹配就直接选择这个方法,这个过程叫做重载解析(会先查找子类,子类没有时才会查找父类)。如果编译器没有找到,或找到多个,都会报错
覆盖问题:如果子类中定义了一个与超类签名(方法名+参数列表)相同的方法、子类方法会对超类方法进行覆盖。(注意子类方法不能低于超类方法的可见性)
静态绑定:当方法被private方法、static 方法、final方法或者构造器修饰,那么编译器可以准确的知道应该调用哪个方法,这种方法称为静态绑定。
方法表:因为每次调用方法都要搜索,时间开销巨大,虚拟机为每个类创建了一个方法表,其中有各个类的签名,节省时间。
6、阻止继承:final类和方法
不允许扩展的类被称为final类,该类不希望被继承使用,其中的方法也会自动的变更为final,域不受影响
将方法或类声明为final的主要目的是:确保他们不会在子类中改变语义
7、强制类型转换:例如 double x = 3.405; int nx = (int)x; 是数值类型的强制转换
对象引用也会用到强制的类型转换(超类可以转换成子类),转换前可以通过 instanceof 字段进行验证(staff[] instanceof Manager)
8、抽象类:
包含一个或多个抽象方法的类本身必须被声明是抽象的
抽象类可以包含具体数据和具体方法
抽象类是占位的角色 具体实现在子类中
抽象类不能被实例化
类即使不含抽象方法,也可以声明为抽象类
抽象方法的应用:可以成为子类的统一化表示(或引用)形式
9、收保护访问 protected
设计的初衷更像是:private和public的折中、设计原则是限制该类的使用、子类是可以使用的
关于访问的归纳:privat(仅对本类可见)、public(对所有类可见)、对本包和所有子类可见(protected)、默认不修饰(对本包可见)
10、Object:所有类的超类
可以使用Object类型的变量引用任何类型的对象:
Object obj = new Employee("Harry Hacker",35000)
在Java中,只有基本类型不是对象(数值、字符、boolean)、所有的数组类型都扩展于Object类
equals : 可以用于比较两个对象是否相等,并具有以下的性质(好像在其他地方也见过):
hashCode方法
散列码(hash code):是由对象导出的一个整型值、对象不同,散列码不同。每个对象都有一个默认的散列码,值为对象的存储地址。
toString 方法 :对象的字符串描述(使用 + 输出对象时,java编译器会默认调用toString方法)
注意:数组的toString被Object覆盖了,所以需要使用静态的 Arrays.toString(数组名) 方法
11、泛型数组列表
数组的缺陷:在创建时确定其大小
解决方案:ArrayList 是一个采用类型参数的泛型类。
定义:ArrayList<Empoyee> staff = new ArrayList<>(此处可以写初始容量);
<> 内(例如:Empoyee)即是泛型,可以通过add方法添加进去泛型、设定第i个元素staff.set(i,harry),访问第i个元素 staff.get(i)
注释:可以通过动态添加ArrayList元素后,在将其转化为固定元素的数组。
ArrayList<Empoyee> 可以转换为 ArrayList<>,反之会收到警告,因为兼容性问题,保证代码不会出现问题即可。
12、对象包装器与自动装箱
基础数据类型:所有的基本类型都有一个与之对应的类(Integer类对应基本类型int),这些类称为包装器(Integer、Long、Float、Double、Short、Byte、Character、Void、Boolean;前六个派生于公共的超类Number)对象包装器是final的,不允许改变
注意:因为每个值分别包装在对象中,所以ArrayList<Integer>效率远远低于int[]
自动拆箱:将一个Integer对象赋值给一个int值时,会自动的进行拆箱(int n = list.get(i) 不需要类型转换,直接为int型)
自动装箱的好处:基本类型和对象包装器可以统一操作,但实际是因为自动拆箱的缘故(例如:两个具有相同值的Integer对象是不相等的)、装箱和拆箱是编译器认可的,而不是虚拟机。
包装器可以进行一些转化(例如字符串转数值 int x = Integer.parseInt(s))、包装器内是不可以修改数值参数的
13、参数数量可变的方法:参数的数量是可以改变的,比如print方法:
public class PrintStream
{
public PrintStream printf(String fmt,Object..., args){ return format(fmt, args); }
}
这里的... 是java代码的一部分,表明方法可以接受任意数量的对象,结合自动装箱拆箱可完成输出函数
14、枚举类
定义:enum Size { S, M, L, X} 代表衣服的尺寸大小
例如:
可以通过:Size.SMALL.toString() 返回 “SMALL”
15、反射
反射库:工具集,可动态操纵Java代码的程序,被大量应用于JavaBeans中,是java组件的体系结构
反射:能够分析类能力的程序称为反射。
特点:
在运行中分析类的能力
在运行中查看对象(toString方法可供所有类调用)
实现通用的数组操作代码
利用Method对象(C++函数指针?)
应用:构造工具
16、Class
java运行系统始终为所有对象维护一个被称为运行时的类型标识,可以通过专门的Java类访问这些信息,保存这些信息的类被称为Class。
常用的方法:
方法一:对象.getClass().getName()
方法二:静态方法:Class.forName(className) (className必须是类名或者接口,否则会抛出异常)
方法三:T.class(例如:int.class/Data.class) T为任意的Java类型比较操作:可以通过==实现
newInstance() : e.getClass().newINstance(),用于快速创建一个类的实例
例子:将forName 与 newInstance 配合使用,可以根据存储在字符串中的类名创建一个对象
String s = "java.util.Date"
Object m = Class.forName(s).newInstance();
17、捕获异常
捕获异常:当程序在运行过程中发生错误时异常的类型:未检查异常(意料之外的,例如 null指针异常)和已检查异常(个人定义的)
已检查异常可通过try{}catch(Exception e){ e.printStackTrace() ;}输出异常信息
18、反射:利用反射分析类的能力
反射机制最重要的内容:检查类的结构
反射中三个重要的类:java.lang.reflect包的三个类,Field/Mehtod/Constructor 分别描述类的域、方法和构造器,三者都有一个getName方法,用于返回项目的名称。
Field类存在getType方法:描述域所属类型的class对象
Method和Constructor类有能够报告参数类型的方法
Method 还有能够报告返回值类型的方法
三个类存在getModifiers方法,可返回整型的数值,描述修饰符
Class中的getFields/getMethods/getConstructors 分别返回类提供的public域、方法和构造器
Class类中的getDeclareFields/getDeclareMethods/getDeclared
Constructors类返回类中声明的全部域、方法、构造器
19、反射:在运行时利用反射分析对象
用途一:利用反射可以查看在编译时还不清楚的对象域(数据域容易获得)
用途二:可以屏蔽访问检查访问私有属性(setAccessible(true))
isAccessible() 返回对象可访问标志 (判断是否私有)
20、反射例子:
使用反射编写泛型数组代码(Array利用反射的实现原理)在Array实现中,需要动态的更新数组的长度(利用既定的copyOf()方法) 但问题是,如何编写一个通用的方法呢:首先的思路是转换为Object对象,但是又如何转回?所有需要记录下数组的类型,通过反射的机制获取(使用Class类的getComponentType方法确定数组对应的类型)所以在扩展时将goodCopyOf 的参数声明为获取到的类型,这样达到了目的!
21、反射:调用任意方法
Method类中存在一个invoke方法,他允许调用包装在当前Method对象中的方法(如何返回类型是基本类型,这返回包装类的类型)可以通过getDeclareMethod方法查找Method对象。
(此处不建议使用了)
22、继承设计的技巧
a 将公共操作和域放在超类
b 不要使用收保护的域
c 使用继承实现“包含”的关系(有些时候并不是包含)
d 除非所以继承的方法都有意义,否则不要使用继承
e 在覆盖方法时,不要改变预期的行为(与超类行为差别过大)
f 使用多态,而非类型信息
g 不要过多的使用反射