关键字:extends
java中多有的继承都是公有继承
已存在的类被称为超类,基类,父类。新类被称为子类,派生类或孩子类
在子类中可以增加域,增加方法或覆盖超类的方法,不能删除继承的任何域和方法
使用关键字super调用超类的方法
class Manager extends Employee{ public double getsalary(){ //调用Employee的getSalary方法 double basesalary = super.getSalary(); return baseSalary + bonus; } }Manager类的构造器不能访问Employee类的私有域,可以通过super实现对超类构造器的调用,必须放在子类构造器的第一条语句
this:引用隐式参数,调用该类其他的构造器
super:调用超类的方法,调用超类的构造器
调用构造器的语句只能作为另一个构造器的第一条语句出现
一个对象变量可以引用多种实际类型的现象被称为多态,在运行时能够自动的选择调用哪个方法的现象称为动态绑定
一个Employee变量既可以引用一个Employee类对象,也可以引用Employee类的任何一个子类的对象
Manager boss = new Manager(); Eployee[] staff = new Employee[3]; staff[0] = boss;staff[0]和boss引用同一个对象,编译器将staff[0]看成Employee对象,staff[0]和boss引用同一个对象
继承层次:由一个公共超类派生出来的类
继承链:在继承层次中,从某个特定的类到其祖先的路径被称为该类的继承链
java不支持多继承
调用对象方法的执行过程:1.编译器查看对象的声明类型和方法名,2.编译器查看调用方法提供的参数类型,3.静态绑定(private,static,final方法,构造器),调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定4.动态绑定时,虚拟机调用与引用对象的实际类型最合适的类的方法
虚拟机预先为每个类创建了一个方法表,列出了所有方法的签名和实际调用的方法
方法的名字和参数列表称为方法的签名
子类方法不能低于超类方法的可见性(权限)
将方法或类声明为final
将某个类的对象引用转换成另外一个类的对象引用
可以将一个子类的引用赋给一个超类变量,如果将一个超类的引用赋给一个子类变量,必须进行类型转换
检查类型转换是否成功
if(staff[1] instanceof Manager) { boss = (Manager) staff[1]; }只作为派生其他类的基类,不作为想使用的特定的实例类
扩展抽象类:在子类中定义部分抽象方法或抽象方法也不定义,必须将子类标记为抽象类.定义全部的抽象方法
Object类
可以使用Object类型的变量引用任何类型的对象
Object obj = new Employee("Harry hacker", 35000);Object类中的equals方法用于检测一个对象是否等于另一个对象,这个方法将判断两个对象是否具有相同的引用,如果两个对象有相同的引用,它们一定相等
public boolean equals(Object otherObject){ if(this == otherObject) return true; if(otherObject == null) return false; if(getClass() != otherObject.getClass()) return false; Employee other = (Employee) otherObject; return name.equals(other.name)&& salary == other.salary&&hireDay.equals(other.hireDay) }getClass方法返回一个对象所属的类
在子类中定义equals方法时,首先调用超类的equals,如果检测失败,对象就不可能相等.如果超类中的域都相等,就需要比较子类中的实例域
class Manager extends Employee { public boolean equals(Object otherObject) { if(!super.equals(otherObject)) return false; Manager other = (Manager) otherObject; return bonus = other.bonus; } }equals方法具有下面的特性:自反性,对称性,传递性,一致性,任意非空引用返回false
equals方法:显式参数命名为otherObject,检测this和otherObject是否引用同一个对象,检测otherObject是否为null(为null 返回false),比较this和otherOj=bject是否属于同一个类(instanceof或getclass),将otherObject转换为相应的类类型变量,对所有需要比较的域进行比较(==比较基本类型域,euqals比较对象域)
散列码是没有规律的,不同对象不散列码不同
返回表示对象值的字符串
动态数组,ArrayList:在添加或删除元素时,具有自动调节数组容量的功能(是一个使用类型参数和泛型类为了制定数组列表保存的元素对象类型)
保存Employee对象的数组列表
ArrayList<Employee> staff = new ArrayList<Employee>();staff.size()返回数组长度,相当于数组的length
add方法为数组添加元素,get得到元素,remove删除元素
Integer类对应基本类型int
对象包装器是不可变的,一旦够早了包装器,就不允许更改包装在其中的值
在比较两个枚举类型的值是,不需要调用equals,直接使用"=="
所有枚举类型都是Enum类的子类
{ public static void main(String[] args) { Scanner in = new Scanner(System.in); String input = in.next().toUpperCase(); //返回指定名字,给定类的枚举常量 Size size = Enum.valueOf(Size.class, input); System.out.println("size="+size); System.out.println("abbreviation=" + size.getAbbreviation()); if(size == Size.EXTRA_LARGE) System.out.println("good job"); } } enum Size { SMALL("S"),MEDIUM("M"),LARGE("L"),EXTRA_LARGE("XL"); private Size(String abbreviation) {this.abbreviation = abbreviation;} public String getAbbreviation() {return abbreviation;} private String abbreviation; }分析类能力的程序
保存每个对象所属的类足迹
一个class对象实际上表示的是一个类型,这个类型未必一定是类
Employee e; //返回一个class类型的实例 Class c1 = e.getClass(); //返回类的名字 e.getName(); //获得class类对象 Class c=Date.class;虚拟机为每个类型管理一个classs对象
创建一个类的实例
e.getClass.newInstance();未检查异常:编译器不会查看是否为这些错误提供了处理器
已检查异常:编译器将会检查是否提供了处理器
try{} catch(){}java.lang.reflect
class类中的getFields,getMethods和getConstructirs方法将分别返回类提供的public域,方法和构造器数组,包括超类的公有成员
getDeclareFields,getDeclareMethods和getDeclareConstructors将分别返回类中声明的全部域,方法和构造器,包括私有和受保护成员,不包括超类的成员
import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.*; public class ReflectionTEST { public static void main(String[] args) { String name; if (args.length > 0) name = args[0]; else { Scanner in = new Scanner(System.in); System.out.println("enter class name:"); name = in.next(); } try { Class c1 = Class.forName(name); Class superc1 = c1.getSuperclass(); String modifiers = Modifier.toString(c1.getModifiers()); if(modifiers.length() > 0) System.out.println(modifiers + " "); System.out.println("class" + name); if(superc1 != null && superc1 != Object.class) System.out.println("extends " + superc1.getName()); System.out.println("\n{\n"); printConstructors(c1); System.out.println(); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.exit(0); } public static void printConstructors(Class c1) { Constructor[] constructors = c1.getDeclaredConstructors(); for(Constructor c : constructors) { String name = c.getName(); System.out.println(" "); String modifiers = Modifier.toString(c.getModifiers()); if(modifiers.length() > 0) System.out.println(name + "("); Class[] paramTypes = c.getParameterTypes(); for(int j = 0;j < paramTypes.length; j++) { if(j > 0) System.out.println(", "); System.out.print(paramTypes[j].getName()); } System.out.println(");"); } } }前面可以查看任意对象的数据域名称和类型
查看数据域的实际内容
toString方法查看任意对象的内部信息
java.lang.reflect包中的Array类允许动态的创建数组
扩展数组的通用方法
Employee[] a = new Employee[100]; a = (EMployee[]) arrayGrow(a); static Object arrayGrow(Object a) { Class c1 = a.getClass(); if(!c1.isArray()) return null; Class componentType = c1.getComponentType; int length = Array.getLength(a); int newLength = length * 11/10 +10; Object newArray = Array.newInstance(componentType,newLength); System.arraycopy(a, 0, newArray, 0, length); return newArray; }arrayGrow()可以扩展任意类型的数组,不仅是对象数组
参数声明为Object类型,不能声明为对象型数组(Object[])
可以使用methid对象实现函数指针的所有操作
最好使用接口和内部类
使用接口进行回调会使得代码的执行速度更快,更易于维护
将公共操作或域放在超类
不要使用受保护的域:子类集合可以访问protected的实例域,破坏了封装性;java中,同一个包的所有类都可以访问protected域,不管它是否为这个类的子类
使用继承实现is-a关系:不要滥用继承
除非所有继承的方法都有意义,否则不要使用继承
在覆盖方法时,不要改变预期的行为:覆盖一个方法时,不应该没理由的改变行为的内涵
使用多态,而不是类型信息:使用多态性提供的动态分配机制
不要过多的使用反射:在运行时查看域和方法,编写系统程序实用.不适合编写应用程序,编译器很难发现程序中的错误