JAVA笔记三:继承

一、超类与子类

  1. 继承格式
    public class Manager extends Emplyee{...}
  2. 调用同名超类方法
    super.getSalary()
  3. 子类构造器
    由于子类不能访问超类的私有域,所以需要调用超类的构造器对这部分私有域初始化,如下所示。注意调用超类的构造器语句必须是子类构造器的第一条语句。倘若没有显示调用超类构造器,将自动调用超类无参数构造器(也可是是默认),如果超类没有无参数构造器,编译器将报错。(很像this)
    super(name,...)
  4. 多态
    在java程序设计语言中,对象变量是多态的。一个超类对象变量可以引用子类对象,但不能通过该对象变量调用子类方法;子类对象变量不能引用超类对象。但存在欺骗现象:
    Manager[] managers = new Manager[10];//超类
    Employee[] staff = managers; //OK
    staff[0] = new Employee("Harry Hacker" ...);//接纳
    managers[0].setBonus(1000)//会引发异常
    
  5. 类方法调用(x.f(args) x为C类对象)
    • 编译器查看对象的声明类型和方法名。一一列举C类对象的名为f的方法和超类中访问属性为public的名为f的方法。
    • 编译器将查看调用方法时提供的参数类型。
    • 如果是private方法,static方法,final方法,或者构造器,编译器将准确知道应该调用哪个方法,称为静态绑定。
    • 当程序运行,并且采用动态绑定调用方法是,虚拟机一定调用与X所引用对象的实际类型最合适的那个类的方法。虚拟机会预先给每个类创建一个方法表。
  6. 阻止继承:final类和方法
    public final class Executive extends Manager{} // 不允许被继承
    public fianl String getName(){}//不允许被覆盖
  7. 将一个超类的引用赋给一个子类变量,必须进行类型转换,在转换之前应该使用instanceof进行检查
    boss = (Manager) staff[1];// ERROR
    if(staff[1] instanceof Manager){
    	boss = (Manager) staff[1];
    }
    
  8. 抽象类abstract,不可以有实例。但可以定义抽象类的对象变量来引用非抽象子类的对象。抽象类还可以包含具体数据和具体方法。
    public abstract class Person{}
    public abstract String getDescription();//不能有实体
  9. 受保护访问
  • 仅对本类可见——private
  • 对所有类可见——public
  • 对本包和所有子类可见——protected
    但是Manager类中的方法只能访问Manager对象中的hireDay域(protected)而不能访问其他Employee对象的这个域。
  • 对本包可见——默认,不需要修饰符
    JAVA静态方法是否可以被继承?
    静态属性、静态方法和非静态的属性都可以被继承和隐藏而不能被重写,因此不能实现多态,不能实现父类的引用可以指向不同子类的对象。

二、object:所有类的超类

  1. 如果没有明确指出超类,object就被认为是这个类的超类,除了基本类型不是对象,其他的都是对象,包括数组,也就是说数组类型也拓展了超类。
  2. equals方法
  • 显式参数明名为otherObject,稍后需要将它转换成另一个叫做other的变量
  • 检测this与otherObject是否引用同一个对象 if(this == otherObject) return true;
  • 检测otherObject是否为空
  • 比较this与otherObject是否属于同一个类if(getClass() != otherObject.getClass() return false;
    如果所有子类都具有统一的语义 if(!(otherObject instanceof ClassName)) return false;
  • 将otherObject转换为相应的类类型变量ClassName other = (ClassName) otherObject
  • 最后比较所有需要比较的域,使用==比较基本类型,使用equals比较对象域。
    对于数组类型的域可以使用静态的Arrays.equals()方法。
    注:@Override 对覆盖方法进行标记,如果没有覆盖父类函数,则会报错。
  1. hashcode方法
    返回对象的散列码。散列码可以是任意的整数,包括整数或负数。两个相等的对象要求返回相等的散列码。
  2. toString方法
    getClass().getName()

三、泛型数组列表

  1. ArrayList
ArrayList staff = new ArrayList<>(); //java SE7 ,之前需要用 new ArrayList();
ArrayList ()// E类型需要是包装类型,ie. int -> Interger
ArrayList(int initialCapacity) // 与声明initialCapacity大小数组不一样,size = 0;
boolean add(E obj) //永远返回true
void add(int index, E obj)
int size()
void ensureCapacity(int capacity) //确保数组列表在不重新分配储存空间的情况下就能够保存给定数量的元素。
void trimToSize()//将数组列表的存储容量削减到当前尺寸。
void set(int index, E obj);
E get(int index)
E remove(int index)

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

  1. Integer类对应基本类型int,这些类称为包装器.包装器类型类似于String,不可变。
    (Integer,Long,Float,Double,Short,Byte,Character,Void,Boolean)这些类属于final
  2. 自动装箱,自动拆箱(从新解绑和绑定新的值)
list.add(3)等价于 list.add(Integer.valueOf(3)
int n = list.get(i) 等价于int n = list.get(i).intValue();
Integer n = 3;
n ++;

五、枚举

public enum Size{
	SMALL("S"), MEDIUM("M")...
	private String abbreviation;
	private Size(String abbreviation) {this.abbreviation = abbreviation;}
}
API
stativ Enum valueOf(Class enumClass, String name)
String toString()
int ordinal() 返回位置,从0开始
int compareTo(E other) 如果出现在other之前,返回一个负值。

六、反射

反射机制可以用来:

  • 在运行时分析类的能力
  • 在运行时查看对象,例如,编写一个toString方法供所有类使用
  • 实现通用的数组操作代码
  • 利用Method对象,这个对象很像C++ 中的指针
  1. Class类 Object 类中的getClass()方法将会返回一个Class类型的实例
    获得Class类对象有三个方法
    Employee e;// ---1
    Class cl = e.getClass();
    
    String className = "java.util.Random";//---2
    Class cl = Class.forName(className);
    
    Class cl1 = Random.class;//--- 3
    Class cl2 = int.class;
    Class cl3 = Double[].class;
    cl2.newInstance(); //调用默认构造器,如果没有,抛出异常
    
    void printStackTrace() // 将Throwable对象和栈的轨迹输出到标准错误流
    e. printStackTrace()
    
  2. 利用反射分析类的能力
1). java.lang.Class 1.0
Field[] getFields() 1.1 //返回包含Field数组,包含这个类和超类的公有域
Field[] getDeclaredFields() 1.1// 包含这个类的所有域和超类的公有域
Method[] getMethods()
Method[] getDeclaredMethods()//还有接口
Constructor[] getConstructors()
Constructor[] getDeclaredConstructors()

2)java.lang.reflect.Field ,java.lang.reflect.Method, java.lang.reflect.Constructor 1.1
int getModifiers()//返回一个描述构造器,方法或域的修饰符的整型数值。
String getName()// 返回名字
Class[] getParameterTypes()// constructor, method中返回描述参数的Class数组
Class getReturnType() // Method类中

3) java.lang.reflect.Modifier 1.1
static String toString(int modifiers)//检测修饰符
static boolean isAbatract(int modifiers)
static boolean isFinal(int modifiers)
static boolean isInterface(int modifiers)
static boolean isNative(int modifiers)
static boolean isPrivate(int modifiers)
static boolean isProtected(int modifiers)
static boolean isPublic(int modifiers)
static boolean isStatic(int modifiers)
static boolean isStrict(int modifiers)
static boolean isSynchronized(int modifiers)
static boolean isVolatile(int modifiers)
  1. 在运行时使用反射分析对象 p201
  2. 使用反射编写泛型数组代码
  3. 通过CLASS类的getMethod方法可以实现函数指针的作用(Method.invoke)

七、继承的设计技巧

  1. 将公共操作和域放在超类
  2. 不要使用受保护的域
  3. 使用继承实现"is-a"关系
  4. 除非所有继承的方法都有意义,否则不要使用继承
  5. 在覆盖方法时,不要改变预期的行为
  6. 使用多态,而非类型信息
  7. 不要过多地使用反射

八、疑问

  1. 反射为什么不导入包也可以分析它的能力

你可能感兴趣的:(java)