0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【java 勉強メモ】オーバーロード時のメソッド実行優先順

0
Last updated at Posted at 2025-07-20

概要

メソッドのオーバーロード時、特に引数の数が同じ場合、どのメソッドが優先して呼び出されるのかをまとめる。
※初学者が書いた勉強メモであることを念頭にお読み下さい。誤りや記載不足の項目がありましたら、コメントにてご指摘いただけますと幸いです。

本編

基本型

Main.java
public class Main {
    public static void main(String[] args) {
        int a = 2;
        int b = 3;
        method(a, b);
    }

    //➀
    public static void method(int a, int b) {
        System.out.println("完全一致");
    }

    //➁
    public static void method(long a, long b) {
        System.out.println("基本型の拡大変換");
    }

    //➂
    public static void method(Integer a, Integer b) {
        System.out.println("オートボクシング");
    }

    //➃
    public static void method(int... num) {
        System.out.println("可変長引数");
    }
}

methodメソッドの実行優先順位は

➀. 実引数の型が、仮引数の型と完全に一致している場合
➁. 実引数の型から仮引数の型へ、基本型の拡大変換ができる場合
➂. 実引数の型から仮引数の型へ、オートボクシングできる場合
➃. 仮引数が、実引数の型の値を可変個受け取れる(可変長引数である)場合

である。

以下の場合は➁Aが優先される。

➁. 基本型の拡大変換
    //➁A
    public static void method(long a, long b) {
        System.out.println("基本型の拡大変換(整数型→整数型)");
    }

    //➁B
    public static void method(double a, double b) {
        System.out.println("基本型の拡大変換(整数型→浮動小数点型)");
    }

コンパイルエラーとなる例

以下のメソッド2つを両方書くとエラーとなる。

    public static void method(long a, int b) {
        System.out.println("基本型の拡大変換 その1");
    }

    public static void method(int a, long b) {
        System.out.println("基本型の拡大変換 その2");
    }

結果

エラー: methodの参照はあいまいです
        method(a, b);
        ^
  Mainのメソッド method(long,int)とMainのメソッド method(int,long)の両方が一致します

上記の例では、両方のメソッドが「➁. 実引数の型から仮引数の型へ、基本型の拡大変換ができる場合」に該当する。
同じ優先順位のメソッドが複数あると、どのメソッドを実行すればいいのか定まらないためエラーが出る。

参照型

Main.java
public class Main {
    public static void main(String[] args) {
        Integer a = 2;
        Integer b = 3;
        method(a, b);
    }
    
    //➀
    public static void method(Integer a, Integer b) {
         System.out.println("完全一致");
    }

    //➁
    public static void method(Number a, Number b) {
        System.out.println("スーパークラス");
    }

    //➂
    public static void method(int a, int b) {
        System.out.println("アンボクシング");
    }

    //➃
    public static void method(Integer... num) {
        System.out.println("可変長引数");
    }
}

methodメソッドの実行優先順位は

➀. 実引数の型が、仮引数の型と完全に一致している場合
➁. 仮引数の型が、実引数の型のスーパークラス型である場合
➂. 実引数の型から仮引数の型へ、アンボクシングできる場合
➃. 仮引数が、実引数の型の値を可変個受け取れる(可変長引数である)場合

である。

以下の場合は➁Aが優先される。

➁. スーパークラス
    //➁A
    public static void method(Number a, Number b) {
        System.out.println("スーパークラス");
    }

    //➁B
    public static void method(Object a, Object b) {
        System.out.println("スーパークラスのスーパークラス");
    }

余談 

参照型→基本型と基本型→参照型

以下のコードはエラーにならない。

Main.java
public class Main {
    public static void main(String[] args) {
        Integer a = 2;
        Integer b = 3;
        method(a, b);
    }

    public static void method(double a, double b) {
        System.out.println("Integerからdouble");
    }
}

結果

Integerからdouble

このメソッドの優先順位は、➂(アンボクシング)と➃(可変長引数)の間となる。
メソッド呼び出しの時にアンボクシング(Integerからint)→基本型の拡大変換(intからdouble)という二段階の手順を踏むため、ただアンボクシングをする時に比べて優先順位が下がるのであろう。

しかし、以下のコードはエラーになる。

Main.java
public class Main {
    public static void main(String[] args) {
        int a = 2;
        int b = 3;
        method(a, b);
    }
    
    public static void method(Double a, Double b) {
        System.out.println("intからDouble");
    }
}

結果

エラー: 不適合な型: intをDoubleに変換できません:
        method(a, b);
               ^

何故前者はエラーにならず、後者はエラーになるのか

javaの言語仕様が記載された上記リンク内「5.3. Invocation Contexts」に、このような記述がある。

Strict invocation contexts allow the use of one of the following:
・an identity conversion (§5.1.1)
・a widening primitive conversion (§5.1.2)
・a widening reference conversion (§5.1.5)
Loose invocation contexts allow a more permissive set of conversions, because they are only used for a particular invocation if no applicable declaration can be found using strict invocation contexts. Loose invocation contexts allow the use of one of the following:
(中略)
・a boxing conversion (§5.1.7)
(中略)
・an unboxing conversion (§5.1.8)
・an unboxing conversion followed by a widening primitive conversion

簡単にまとめると、「実引数の型が、仮引数の型と完全に一致している」「実引数の型から仮引数の型へ、拡大変換できる」といった厳密なメソッドが呼び出せない時のみ、より緩い条件でのメソッド呼び出しができる。本編で挙げた「➂. 実引数の型から仮引数の型へ、オートボクシング/アンボクシングできる場合」は、緩い条件でのメソッド呼び出しに含まれる。
そして先ほど述べた、「メソッド呼び出しの時にアンボクシング→基本型の拡大変換という二段階の手順を踏む場合」も、緩い条件の一種として仕様上許可されている。

逆に、「基本型の拡大変換→オートボクシングという二段階の手順を踏む場合」はリンク先に記載がない(=仕様上許可されていない)。つまり、実引数の型intをdoubleに、doubleをDoubleに、自動で変換してメソッドを呼び出すことはできないのである。

ちなみに、「オートボクシング→参照型の拡大変換」も仕様上許可されている。つまり、以下のコードはエラーにならない。無論、優先順位は本編➂(オートボクシング)と➃(可変長引数)の間である。

Main.java
public class Main {
    public static void main(String[] args) {
        int a = 2;
        int b = 3;
        method(a, b);
    }
    
    public static void method(Number a, Number b) {
        System.out.println("intからNumber");
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?