Javaの基本シリーズ() - 過負荷(過負荷)と書き換え可能(上書き)

まず、メソッドシグネチャ

  • Javaでは、いわゆるメソッドのシグネチャはメソッド名+パラメータ・タイプ
  • 例えばこの方法はpublic void fun(int a) throws IOException{ }、メソッドのシグネチャはこちらfun(int)
  • 注:戻り型は、メソッドシグネチャの一部ではありません

第二に、メソッドのオーバーロード(過負荷)

  • まず、メソッドのオーバーロードの定義で見てみましょう

メソッドのオーバーロードは、で定義されたクラスを意味するメソッドと同じ名前の複数が、多くの方法は、パラメータまたはパラメータの種類毎に異なる要件を有しますオーバーロードされたメソッドを呼び出す場合、Javaコンパイラは、適切な方法を選択するタイプとパラメータの数によって呼び出されるメソッドを確認します。この方法は、多くの場合、同様のタスクの完全なセットを作成するために使用されるが、パラメータまたはプロセスパラメータのパラメータの異なる注文番号またはタイプでオーバーロード。[1] Javaメソッドがオーバーロードであることを、クラスのメソッドの複数を作成することができ、それらは、同じ名前を有していてもよいが、異なるパラメータ、すなわち、パラメータまたは異なる数またはパラメータの異なるタイプを有していなければなりませんメソッドを呼び出すときに、異なるパラメータの数と種類、およびパラメータの順序を渡すことによって、それらを使用する方法を決定するために、詳細な合格

  • その後、我々は、カウント方法は、オーバーロードした場合、次のような状況を議論するために来ますか?

同じ名前と同じパラメータリストが、異なる戻り値の2.1方法?

  • クラスが持っている場合int fun(int a)double fun(int a)の二つの方法、計算方法は、それをオーバーロード?直接コードに
public class MyOverload {
    public void fun(int a) {

    }

    public double fun(int a) {

        return 0.0;
    }
}
  • 業績
    • コンパイルエラーは、エラーメッセージは次のとおりです。'fun(int)' clashes with 'fun(int)'; both methods have same erasure 'fun(int)' is already defined in 'thinking.about_override_overload.MyOverload'おそらく、クラスが同じメソッドシグネチャを持っていることを意味しますfun(int)
    • パラメータリストは異なる01.過負荷同じ戻り値
  • 結論
    • 二つの方法の場合、メソッド名と同じパラメータリストが、戻り値は同じではありません、これはされて過負荷になりません同じメソッド名とパラメータリストため、ある同一のメソッドシグネチャ、および同じクラスれる二つの同一のメソッドのシグネチャが存在を持つことが許されていません

2.2同じ名前のメソッドが、パラメータと戻り値のリストが異なりますか?

  • 次のように上記のコード例は、変更された場合
public class MyOverload {
    public void fun(int a) {

    }

    public double fun(int a, int b) {

        return 0.0;
    }
}
  • 業績
    • でコンパイルされました
  • 結論
    • もし二つの方法の方法と同じ名前が、パラメータと戻り値のリストが異なっている、これはあるメソッドのオーバーロードの一部ので、戻り値とは何の関係もないのオーバーロードメソッドは、パラメータリストから二つの異なる方法が、それは別のメソッドシグネチャ(同じメソッド名)を表し、それはリロードに属します。

同じ名前と同じ引数リストが、例外の2.3方法が異なるスローされますか?

  • 直接コードに
public class MyOverload {
    public void fun(int a) throws IOException {

    }

    public void fun(int a) throws CloneNotSupportedException {

    }
}
  • 実際には、上記の2つの例から答えを起動することができます。どんなにあなたがスローされた例外を変更する方法なので、これらの2つの方法のメソッドシグネチャは同じです確かに、私はリロードに属していないので、コンパイラではありません。
  • 02.過負荷投げ異なります

2.4まとめ

  • この方法は、オーバーロードを構成する唯一の方法で署名されたメソッド名とパラメータリストと。同じメソッド名とパラメータリストが同じでない場合には、それは大きな負荷を構成しています。以下とは何の関係もオーバーロードしないという方法を覚えておいてください。
    • メソッドのオーバーロードと独立した戻り値
    • メソッドのオーバーロードとは無関係のスローされます
    • 方法重载与 参数名称无关
  • 对于为什么方法重载只和方法名和参数列表有关,而和返回值无关呢?在《Java编程思想(第4版)》中有这么一段话:

5.2.3 以返回值区分重载方法
读者可能会想:“在区分重载方法的时候,为什么只能以类名和方法的参数列表作为标准呢?能否考虑用方法的返回值来区分?”
比如下面两个方法,虽然它们有同样的名字和形式参数,但却很容易区分他们:
void f(){}
it f(){return 1;}
只要编译器可以根据语境明确判断出语义,比如在int x=f()中,那么的确可以据此区分重载方法。不过,有时你并不关心方法的返回值,你想要的是方法调用的其他效果(这常被称作为“为了副作用而调用”),这时你可能会调用方法而忽略其返回值。所以,如果像下面这样调用方法:
f();
此时Java如何才能判断该调用那一个f()呢?别人该如何理解这中代码呢?
因此 ,根据方法的返回值来区分重载方法是行不通的。

  • 也就是说,假如Java允许一个类中有两个具有相同方法签名而返回值不同的方法存在,那么当我们忽略返回值而调用方法的时候,JVM将不知道调用哪个方法,所以这是不允许的。

三、方法重写(Override)

  • 我们一样先来看一下方法重写的定义
  • 在Java和其他一些高级面向对象的编程语言中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
  • 若子类中的方法与父类中的某一方法 具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。 如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。
  • 了解完定义后,我们来验证以下情况是否符合方法重写

3.1 重写父类方法是否可以更改参数列表?

  • 首先定义父类A,其中的方法声明为 protected void fun(int a, int b)
public class A {
    protected void fun(int a, int b) {
    
    }
}
  • 定义类B继承类A,并将其方法声明改为 protected void fun(int a)
public class B extends A {
    @Override
    protected void fun(int a) {
    
    }
}
  • 运行结果
    • 如果有@Override注解的话会编译报错,错误信息为Method does not override method from its superclass 大概意思是说该方法不是从父类所继承,所以不能加@Override注解03.書き換えの方法は、パラメータリストを変更します
  • 结论
    • 重写父类方法不可以更改参数列表,编译报错的原因是加上了@Override注解,而此时的方法签名与父类方法签名不一致,所以出错。去掉@Override的话不报错,但是由于方法签名不一致,已经不算重写了

3.2 重写父类方法是否可以更改返回值?

  • 从上面的例子我们不妨大胆猜想,如果返回值与父类不一致,那么在加上@Override的情况下就会报错。真实情况是否是这样呢?我们来验证一下
  • 第一种情况:当返回值是基本数据类型时,更改子类B的代码如下,将其返回值改为void
public class B extends A {
    @Override
    protected double fun(int a, int b) {
    	
    	return 0.0;
    }
}
  • 运行结果
    • 编译报错,错误信息为'fun(int, int)' in 'thinking.about_override_overload.B' clashes with 'fun(int, int)' in 'thinking.about_override_overload.A'; attempting to use incompatible return type,大概意思是说B类中的fun()与A类中的fun()返回类型冲突04.リライトの戻り値の変更
  • 结论
    • 当返回值是基本数据类型时方法重写不可以更改返回值
  • 第二种情况:当返回值不是基本数据类型,也就是引用数据类型时,更改A类和B类的代码如下
public class A {
    protected A fun(int a, int b) {

        return new A();
    }
}
public class B extends A {
    @Override
    protected A fun(int a, int b) {

        return new A();
    }
}
  • 运行结果
    • 编译通过
  • 继续修改子类B,将其返回值改为B(B 是 A 的子类)
public class B extends A {
    @Override
    protected B fun(int a, int b) {

        return new B();
    }
}
  • 运行结果
    • 程序一样编译通过
  • 继续修改子类B,将其返回值修改为 Object (Object 是 A 的父类)
public class B extends A {
    @Override
    protected Object fun(int a, int b) {

        return new Object();
    }
}
  • 运行结果
    • 编译报错,提示类型冲突。
  • 结论
    • 从上面的例子我们可以得出,重写方法时是否可以更改返回值 由根据父类方法的返回值决定*
      • 如果父类方法返回值是基本数据类型,那么子类重写父类方法时 不可以更改其返回值
      • 如果父类方法返回值是引用数据类型,那么子类重写父类方法时 可以更改其返回值,但是前提是子类方法的返回值类型必须与父类方法的返回值类型一致,或者子类方法的返回值类型是父类返回值类型的子类

3.3 重写父类方法是否可以更改访问权限修饰符?

  • 父类A的fun()的访问权限修饰符为protected,将子类B的fun()的访问权限修饰符改为private,直接上代码
public class B extends A {
    @Override
    private void fun(int a, int b) {
       
    }
}
  • 运行结果
    • 编译报错,错误信息为'fun(int, int)' in 'thinking.about_override_overload.B' clashes with 'fun(int, int)' in 'thinking.about_override_overload.A'; attempting to assign weaker access privileges ('private'); was 'protected',大概意思是说子类使用了更严格的访问权限05.書き換え、変更アクセス修飾子
  • 结论
    • 方法重写可以更改访问权限修饰符,但是前提是子类的访问权限不能比父类更严格。也就是说,如果父类使用的是public,那么子类就不可以使用protected、default、private;如果父类使用的是protected,那么子类就不可以使用default、private。以此类推…
  • 说明
    • 访问权限的范围从大到小依次是:public > protected > default(包访问权限) > private

3.4 重写父类方法是否可以更改所抛出异常?

  • 修改父类A,为其抛出 IOException
public class A {
    protected void fun(int a, int b) throws IOException {

    }
}
  • 修改子类B,为其抛出 IOException 和 CloneNotSupportedException
public class B extends A {
    @Override
    protected void fun(int a, int b) throws IOException, CloneNotSupportedException {
        
    }
}
  • 运行结果
    • 编译报错,出错信息为'fun(int, int)' in 'thinking.about_override_overload.B' clashes with 'fun(int, int)' in 'thinking.about_override_overload.A'; overridden method does not throw 'java.lang.CloneNotSupportedException',意思是说类B的fun()不能抛出CloneNotSupportedExceptionここに画像を挿入説明
  • 继续修改子类B,将抛出的异常全部去除
public class B extends A {
    @Override
    protected void fun(int a, int b) {
        
    }
}
  • 运行结果
    • 编译通过
  • 继续修改子类B,为其抛出 Exception
public class B extends A {
    @Override
    protected void fun(int a, int b) throws Exception {

    }
}
  • 运行结果
    • 编译不通过,因为抛出的 Exception是IOException的父类
  • 继续修改子类B,为其抛出 IOException 和 FileNotFoundException
public class B extends A {
    @Override
    protected void fun(int a, int b) throws IOException, FileNotFoundException {

    }
}
  • 运行结果
    • 编译通过,因为 FileNotFoundException是IOException的子类
  • 结论
    • 方法重写可以更改抛出的异常,但是前提是子类方法所抛出的异常不能比父类方法所抛出的异常范畴更大
    • 也就是说,假如父类抛出IOException,那么子类不能抛出Exception (因为其是IOException的父类),也不可以多抛出CloneNotSupportedException (因为CloneNotSupportedException并不是IOException的子类),但是可以多抛出一个FileNotFoundException (因为其是IOException的子类)

3.5 小结

  • 对于方法重写来说,需要注意以下几点
    • 发生方法重写的两个方法 返回值、方法名、参数列表必须完全一致 (子类重写父类的方法)
    • 子类抛出的异常下 不能超过父类相应方法抛出的异常 (子类异常不能大于父类异常)
    • 子类方法的 访问级别不能比父类相应方法的访问级别更严格 (子类访问级别不能低于父类访问级别)
    • 子类重写父类方法的 返回值类型不能大于父类方法的返回值类型,即是说 子类方法的返回值必须和父类方法的返回值相同或是其子类

4. 重载和重写的区别

  • 从定义来说
    • 重载是函数名称相同,参数的类型或者个数不同
    • 重写是函数名称、参数类型及个数完全相同
  • 从范围来说
    • 重载是发生在一个类中
    • 重写是发生在继承关系中
  • 从限制来说
    • 重载没有访问权限和返回值的限制
    • 重写不能拥有比父类更严格的访问权限,不能抛出比父类范畴更大的异常,返回值不能是父类方法返回值的父类
リリース元の4件の記事 ウォンの賞賛2 ビュー127

おすすめ

転載: blog.csdn.net/a1092882580/article/details/103493047