java核心技术第五章 继承j

动态绑定

        原则: 调用实际类型的方法 

  •                  Emplogee e = new Manager();    e.method();
  •                  将会优先调用 Manager(子类)中的方法,除非Emplogee(父类)中没有该方法
  •                  即指向子类型的父类型变量,不能调用父类型不存在的方法。
  •                  e.method();  调用时,虚拟机知道其实际类型,自动匹配实际类型中的方法。 

  •                  由于动态绑定的存在,推荐使用多态,

强制类型转换

         强转的原因: 子类型变量不能引用父类型实例,但是想要调用子类型独有的方法。

public class TypeChange {
  Manager manager = new Manager();
  Emplogee e = manager;
  Manager m =  e; //报错 编译不通过
}

public class TypeChange {
  Manager manager = new Manager();
  Emplogee e = manager;
  Manager m = (Manager) e;  //通过强转
// 强转以后就可以调用子类增加的方法
}
  • 尽量通过设计较好的超类避免类型转换,通过动态绑定,通过父类型变量调用子类型方法。

Obiect:所有类的超类

  •     equals 方法   :    在Object中 该方法判断两个变量的引用是否相同,但实际上会覆盖用特定的方法比较项是否相同
  •     ????  : 5.2  equals()方法,相等测试与继承,hashCode()的讲解不是很理解。

    对书上正确  equals()方法 的理解

    @Override
    public boolean equals(Object otherobj) {
        if(this == otherobj) return true;
        if(otherobj == null) return false;
        
        //若每个子类的 equals() 方法有所变化,则使用此条。
        if(this.getClass() != otherobj.getClass()) return  false;
        //若所有子类的 equals() 方法语义都相同,则使用此条
        if(!(otherobj instanceof ClassName)) return  false;
        
        //转为相应类型
        ClassName  obj = (ClassName)otherobj;
        //比较相应的域
        return field1 = obj.field1
                && Objects.equals(field2,obj.field2)
                && ...
    }

反射

  • 再运行时分析类的能力
  • 在运行时查看对象
  • 实现通用的数组操作代码
  • 利用Method对像
  • Class 类

  • 每一个类型对应一个Class类的实例。
  • 获取类型Class实例的三种方法:
  1. Class c = e.getClass(); or      Class c = Employee.Class
  2. Class c = Class.forName(className)  该方法可以通过类名或者接口名获取对应的Class实例,另外一个作用,通过该方法实现手动加载类。运行该方法,将会加载className这个类。
  3. Class c = T.class   T为任意的Java类型。
  4. e.getClass().newInstance()  该方法通过默认构造器初始化一个与e同类型的实例。若要给实例提供参数,要使用Constructor 类的newInstance方法。
  • 利用反射分析类的能力

  • 检查类的结构 : 从类的层面上解析类,下边还将在对象层面分析对象。在类的层面上解析类,得到的所有实例都是与类型挂钩,而与具体的实例无关。
  • 在java.lang.reflect包中有三个类Field、Method和Constructor分别用于描述类的域、方法和构造器。
  • 这三个类都有一个叫做getName的方法,用来返回项目的名称。Field 类有一个getType方法,用来返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method 类还有一一个可以报告返回类型的方法。
  • 这三个类还有一个叫做getModifiers的方法,它将返回一一个整型数值,用不同的位开关描述public和static这样的修饰符使用状况。
  • 可以利用java.lang.reflect包中的Modifier类的静态方法分析getModifers返回的整型数值。例如,可以使用Modifier类中的isPublic、isPrivate 或isFinal判断方法或构造器是否是public、private或final。我们需要做的全部工作就是调用Modifer类的相应方法,并对返回的整型数值进行分析,另外,还可以利用Modifier.toString方法将修饰符打印出来。
  • Class类中的getFields、getMethods 和getConstructors方法将分别返回类提供的public域、方法和构造器数组,其中包括超类的公有成员。
  • Class 类的getDeclareFields、getDeclareMethods和getDeclaredConstructors方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超类的成员。

  • 在运行时使用反射分析对象

  • 通过使用反射对类进行解析后,可以得到 Field 实例,这个实例与解析的实例中的一个域相对应
  • Field 通过get set方法,可以读取设置 ,解析该Field对应的实例的域。
  • 对于 私有域,通过setAccessible()方法设置,使得私有域也可以访问。
  • 示例:其中V的实际类型为String
  • Employee harry = new Employee("Harry Hacker", 35000, 10, 1, 1989); 
    Class cl = harry.getClass0; 
    // the class object representing Employee 
    Field f = cl.getDeclaredFieldC'name"): 
    // the name field of the Employee class 
    Object v = f.get(harry); 
    // the value of the name field of the harry object, i.e., the String object "Harry Hacker"
  • 书中关于通用toString 方法的描述不是很理解,只知道其对与所有的类型都采用相同的格式输出。

  • API

  • 使用反射编写泛型数组代码

  • 使用 Class 类(只能定义表示数组的类对象)的 getComponentType方法确定数组对应 的类型。 

  • 需要 java, lang.reflect 包中 Array 类的一些方法。其中最关键的是 Array类中的静态方法 newlnstance, 它能够构造新数组。在调用它时必须提供两个参数,一个是数组的元素类型,一个是数组的 长度。 

  • 以通过调用 Array.getLength(a) 获得数组的长度, 也可以通过 Array类的静态 getLength 方法的返回值得到任意数组的长度

  • 此处需要注意: class类的 getclass方法 将会返回其实际类型对应的 Class实例

  • API       componentType数组类型

  • 调用任意方法

  • 与动态解析对象的域一样,类似的可以动态的调用其方法,方式大致都一样。
  • method的invoke方法仅在必要时使用,因为其要经过多次类型转换
  • method 的获取: class.getmethod()  ;  class.getDeclareMethod
  • class.getmethod(String name,class...parameterTypes) name为方法名,后边是参数类型(重载的存在)
  • API

猜你喜欢

转载自blog.csdn.net/qq_38003454/article/details/82725862