重载(overloading)与重写(overriding)

问题:重载(overloading)与重写(overriding)的区别

1.equals比较问题
public class MethodOverrideVsOverload {

	public boolean equals( MethodOverrideVsOverload other ) {
	     System.out.println("MethodOverrideVsOverload equals method reached" );
	     return true;
	   }
	 
	 public static void main(String[] args) {
	  Object o1 = new MethodOverrideVsOverload();
	  Object o2 = new MethodOverrideVsOverload();
	 
	  MethodOverrideVsOverload o3 = new MethodOverrideVsOverload();
	  MethodOverrideVsOverload o4 = new MethodOverrideVsOverload();
	 
	  if(o1.equals(o2)){
	   System.out.println("objects o1 and o2 are equal");
	  }
	 
	  if(o3.equals(o4)){
	   System.out.println("objects o3 and o4 are equal");
	  }
	 }
}


Console输出:
MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal


结果分析与解释:
1.单元测试类中第15运行结果为false
分析:
(1)对于object类型,其== 与 equals 同样都是比较内存地址,所以为false,
(2)大多数的非final对象类方法都会被子类重写,若没有显示的声明extends父类,默认继承Object类,而只要重写object中equals方法,equals比较的就是对象的内容而非地址
==与equals的区别
(3)可见,在单元测试类中的equals方法,并非是方法重写,而是方法重载;另外一点,其没有@Override标签
注意:
(1)标签,不要删除,其可以帮你检查错误,若重写的方法有函数名称、参数类型的错误,会给与提示,比如:toString() 可能会写成 tostring() ,若这样就是不同的两个方法了,也就不是子类重写父类的方法了
(2)运行报错:
ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
JDWP exit error AGENT_ERROR_NO_JNI_ENV(183):  [../../../src/share/back/util.c:820]

解决方法:在Main方法中末尾添加System.exit(0);
参考文献:
JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
System.exit(0);与return的区别
2.如何解决——添加@Override
public class MethodOverrideVsOverload {

	@Override
	public boolean equals( Object obejct ) {
	     System.out.println("MethodOverrideVsOverload equals method reached" );
	     return true;
	   }
	 
	 public static void main(String[] args) {
	  Object o1 = new MethodOverrideVsOverload();
	  Object o2 = new MethodOverrideVsOverload();
	 
	  MethodOverrideVsOverload o3 = new MethodOverrideVsOverload();
	  MethodOverrideVsOverload o4 = new MethodOverrideVsOverload();
	 
	  if(o1.equals(o2)){
	   System.out.println("objects o1 and o2 are equal");
	  }
	 
	  if(o3.equals(o4)){
	   System.out.println("objects o3 and o4 are equal");
	  }
	 }
}

Console输出:
MethodOverrideVsOverload equals method reached
objects o1 and o2 are equal
MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal


3.
(1)重写与重载的对比
名称 起作用时间 举例 含义
重载 编译时 静态绑定 静态绑定意味着JVM在编译时决定调用的类或方法
重写 运行时 动态绑定 动态绑定时,JVM是在运行时决定调用的类或方法,动态绑定设计是多态的基础

运行时与编译时
(2)子类重写父类方法时注意
内容 注意事项
参数 不可变(包括参数类型和个数)
返回类型 不可变,除了协变返回类型或其子类型(covariant (subtype) returns)
异常 子类中可以抛出更少的异常,但绝对不能抛出父类中没有定义的已检查异常
访问权限 比父类中对应方法更宽松,访问权限要大于父类的访问权限
调用 运行时(也就是动态绑定),根据对象类型来决定调用的具体方法

(3)代码举例
a.重载
Test.java
public class Test {

    static final  int number1 = 5;
    
    static final  int number2 = 6;
 
    static int number3 = 5;
 
    static int number4= 6;
 
    public static void main(String[ ] args) {
 
          int product1 = number1 * number2;         //line A
 
          int product2 = number3 * number4;         //line B
		  
		  System.out.println(product1 + " "+product2);
		  
		  showMessage(product1);
		  
		  showMessage(String.valueOf(product2));
 
    }

    public static void showMessage(String message){
		System.out.println(message+"123");
	}
	public static void showMessage(int message){
		System.out.println(message+1234);
	}
}

编译后Test.class

import java.io.PrintStream;

public class Test
{
  static final int number1 = 5;
  static final int number2 = 6;
  static int number3 = 5;
  static int number4 = 6;

  public static void main(String[] paramArrayOfString)
  {
    int i = 30;

    int j = number3 * number4;

    System.out.println(i + " " + j);

    showMessage(i);

    showMessage(String.valueOf(j));
  }

  public static void showMessage(String paramString)
  {
    System.out.println(paramString + "123"); }

  public static void showMessage(int paramInt) {
    System.out.println(paramInt + 1234);
  }
}


说明:编译期间,根据参数类型即决定调用第几个方法
即编译器可以根据参数的类型来选择使用哪个方法。

b.重写
public class A {
	public void showMessage(String message){
		System.out.println(message);
	}
}
public class B extends A {
	public void showMessage(String message){
		System.out.println(message+"1");
	}
	public static void main(String[] args) {
		test();
	}	
	public static void test(){
		A test = new B();
		test.showMessage("1");
	}
}

编译器是没法知道传入的参数reference的类型是A还是B。因此,只能够在运行时,根据赋给输入变量“reference”的对象的类型(例如,A或者B的实例)来决定调用的方法.
上面测试用例输出结果:11,运行的是子类重写的方法
参考文献:
http://www.importnew.com/2228.html
http://www.importnew.com/1796.html

猜你喜欢

转载自mingyundezuoan.iteye.com/blog/2211930