tij学习笔记 多态,继承

 

1.子类可以重载父类方法 overload

public class SubClass {
 void f(){
  System.out.println("SubClass.f()");
 }

 
 public static void main(String[] args) {
  Derived a = new Derived();
  a.f();
  a.f(2);
  
 }


}
class Derived extends SubClass {
 void f(int i){
 System.out.println("Derived f()");
 }
}

结果

SubClass.f()
Derived f()

2.子类覆盖父类中的方法 override

public class SubClass {
 void f(){
  System.out.println("SubClass.f()");
 }

 
 public static void main(String[] args) {
  Derived a = new Derived();
  a.f();
  
  
 }


}
class Derived extends SubClass {
 void f(){
 System.out.println("Derived f()");
 }
}

运行结果

Derived f()

3.下面是动态绑定:

public class SubClass {
 void f(){
  System.out.println("SubClass.f()");
 }

 
 public static void main(String[] args) {
  SubClass a = new Derived();
  a.f();
  
  
 }


}
class Derived extends SubClass {
 void f(){
 System.out.println("Derived f()");
 }
}
结果:

Derived f()

 

什么是动态绑定?

thinking in java 中的解释:这时a2f()方法可以调用,但是编译器会调用哪个呢?

分为前期绑定和后期绑定.

前期绑定就是运行前绑定.

 

后期绑定:

编译器会在运行时根据对象的类型进行绑定,这时是一个SubClass引用一个Derived对象,会跟据对象类型绑定子类方法( Derived对象,所以绑定子类f()方法 ).

java中除了static fanal方法以外都是后期绑定.通常情况下不必判断后期绑定,编译器自动后期绑定.

这是多态重要的思想.

 

数据成员不会动态绑定


public class SubClass {
 int i = 7;
 void f(){
  System.out.println("SubClass.f()");
 }

 
 public static void main(String[] args) {
  SubClass a = new Derived();
  a.f();
  System.out.println(a.i);
  
  
 }


}
class Derived extends SubClass {
 int i = 100;
 void f(){
 System.out.println("Derived f()");
 }
}

运行结果

Derived f()
7

 

4.向下转型和运行时类型识别

public class SubClass {
 int i = 7;
 void f(){
  System.out.println("SubClass.f()");
 }

 
 public static void main(String[] args) {
  SubClass a = new Derived();
  //! a.f(8);//
编译时不能通过.

((Derived)a).f(8);//必须向下转型为Derived引用
  
  
 }


}
class Derived extends SubClass {
 int i = 100;
 void f(int j){
 System.out.println("Derived f()");
 }
}

运行结果

Derived f()

ps:动态绑定(dynamic binding) --core java 2 volume 1  7th edition

It is important to understand what happens when a method call is applied to an object. Here are the details:

  1. The compiler looks at the declared type of the object and the method name. Let's say we call x.f(param), and the implicit parameter x is declared to be an object of class C. Note that there may be multiple methods, all with the same name, f, but with different parameter types. For example, there may be a method f(int) and a method f(String). The compiler enumerates all methods called f in the class C and all public methods called f in the superclasses of C.

编译器检查对象的声明类型和方法名,假设我们调用x.f(param),隐式变量x被声明为C类的一个对象,注意:x对象可能有多个同名的方法,f,但是有不同的参数类型,例如,可能是f(int)f(String).编译器列举C所有方法名为f的方法和C的超类的所有public,方法名为f的方法.

Now the compiler knows all possible candidates for the method to be called.

  1. Next, the compiler determines the types of the parameters that are supplied in the method call. If among all the methods called f there is a unique method whose parameter types are a best match for the supplied parameters, then that method is chosen to be called. This process is called overloading resolution. For example, in a call x.f("Hello"), the compiler picks f(String) and not f(int). The situation can get complex because of type conversions (int to double, Manager to Employee, and so on). If the compiler cannot find any method with matching parameter types or if multiple methods all match after applying conversions, then the compiler reports an error.

接着,编译器检查所有方法的参数类型,如果所有名为f的方法的参数签名有唯一一个跟f(param)中的方法参数签名匹配,则这个方法被调用.这个过程叫做overloading resolution(重载?),例如 x.f(“hello”)…….not f(int)///… 类型转换问题…,,如果在类型转换后不能发现匹配方法或者发现多个匹配方法,编译器报错.

Now the compiler knows the name and parameter types of the method that needs to be called.

  1. If the method is private, static, final, or a constructor, then the compiler knows exactly which method to call. (The final modifier is explained in the next section.) This is called static binding. Otherwise, the method to be called depends on the actual type of the implicit parameter, and dynamic binding must be used at run time. In our example, the compiler would generate an instruction to call f(String) with dynamic binding.

如果方法是private,static,final或者是构造器,编译器会准确的知道调用那个方法.这叫静态绑定.否则方法调用则依靠隐式参数类型,且运行期间必须使用动态绑定.

  1. When the program runs and uses dynamic binding to call a method, then the virtual machine must call the version of the method that is appropriate for the actual type of the object to which x refers. Let's say the actual type is D, a subclass of C. If the class D defines a method f(String), that method is called. If not, D's superclass is searched for a method f(String), and so on.

当程序运行和使用动态绑定方法时,虚拟机必须调用x引用的真正的实际对象类型所匹配的方法.(翻译不明白),假设实际类型时D,C的子类,如果D定义了方法 f(String),那就调用这个方法.如果没有,则在D的超类中搜索.超类中没有,在超类的超类中搜索,依次类推

It would be time consuming to carry out this search every time a method is called. Therefore, the virtual machine precomputes for each class a method table that lists all method signatures and the actual methods to be called. When a method is actually called, the virtual machine simply makes a table lookup. In our example, the virtual machine consults the method table for the class D and looks up the method to call for f(String). That method may be D.f(String) or X.f(String), where X is some superclass of D.

There is one twist to this scenario. If the call is super.f(param), then the compiler consults the method table of the superclass of the implicit parameter.

 

  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值