ลายเซ็นของเมธอดใน Java มีประเภทการส่งคืนหรือไม่


102

เมธอดซิกเนเจอร์ในคลาส / อินเตอร์เฟส Java มีประเภทการส่งคืนหรือไม่

ตัวอย่าง:

Java ทราบความแตกต่างระหว่างสองวิธีนี้หรือไม่:

public class Foo {
    public int  myMethod(int param) {}
    public char myMethod(int param) {}
}

หรืออาจเป็นเพียงชื่อวิธีการและรายการพารามิเตอร์เท่านั้นที่มีความสำคัญ?


7
อย่างไรก็ตามมีข้อผิดพลาดในการจัดการ generics ใน Java 6 ซึ่งทำให้คุณมีทั้งสองวิธีเนื่องจาก JVM ใช้ประเภทการส่งคืนในลายเซ็นและเรียกใช้แบบเลือก สิ่งนี้ได้รับการแก้ไขใน Java 7. vanillajava.blogspot.co.uk/2011/02/…
Peter Lawrey

คำตอบ:


146

การอ้างอิงจากOracle Docs :

คำจำกัดความ: องค์ประกอบสองส่วนของการประกาศวิธีการประกอบด้วยลายเซ็นของวิธีการ - ชื่อของวิธีการและประเภทพารามิเตอร์

ป้อนคำอธิบายภาพที่นี่

เนื่องจากคำถามได้รับการแก้ไขเพื่อรวมตัวอย่างนี้:

public class Foo {
    public int  myMethod(int param) {}
    public char myMethod(int param) {}
}

ไม่คอมไพลเลอร์จะไม่ทราบความแตกต่างเนื่องจากลายเซ็นของพวกเขา: myMethod(int param)เหมือนกัน บรรทัดที่สอง:

    public char myMethod(int param) {}

จะทำให้คุณสามารถ error: method ถูกกำหนดไว้แล้วในคลาสซึ่งเป็นการยืนยันข้อความข้างต้น


คุณหมายความว่าเราไม่สามารถมีสองเมธอดในคลาสที่มีชื่อเมธอดเดียวกันพารามิเตอร์เดียวกันกับประเภทผลตอบแทนที่แตกต่างกัน?
Kasun Siyambalapitiya

6
@KasunSiyambalapitiya แน่นอนเราทำไม่ได้ วิธีคอมไพเลอร์จะทราบว่าวิธีการที่จะเรียกในสถานการณ์เช่นนี้foo.bar(baz);?
Kolyunya

@Jops เกิดอะไรขึ้นถ้าเรามีคำหลักพ่น? มันเป็นของลายเซ็นด้วยหรือ?
Akila Amarasinghe

19

class method signature ใน Java มี return type หรือไม่

ใน Java ไม่มี แต่ใน JVM นี้จะทำให้เกิดความสับสนอย่างชัดเจน

ลายเซ็นเมธอดอินเตอร์เฟสใน Java มีประเภทการส่งคืนหรือไม่

เช่นเดียวกับวิธีการเรียน

หรือเฉพาะชื่อวิธีการและรายการพารามิเตอร์?

ชื่อเมธอดและประเภทพารามิเตอร์สำหรับ Java ตัวอย่างเช่นคำอธิบายประกอบและชื่อพารามิเตอร์ไม่สำคัญ


1
คุณหมายถึงอะไรโดย "ใน Java ไม่ได้ แต่เป็น JVM" คุณสามารถอธิบายรายละเอียดเกี่ยวกับวิธีการใน JVM ได้หรือไม่?
Tarun Maganti

3
@TarunMaganti JVM มีประเภทการส่งคืนในลายเซ็นของวิธีการ Java เป็นภาษาไม่ได้
Peter Lawrey

3
@xyz นี่คือสิ่งที่คุณสามารถเห็นได้จากการอ่านรหัสไบต์ แต่ไม่ใช่รหัส Java รหัสไบต์ใด ๆ แสดงสิ่งนี้
Peter Lawrey

8

ในระดับ bytecode "return type" เป็นส่วนหนึ่งของลายเซ็นของวิธีการ พิจารณาสิ่งนี้

public class Test1  {
    public Test1 clone() throws CloneNotSupportedException {
        return (Test1) super.clone();
    }
}

ใน bytecode มี 2 วิธีการโคลน ()

public clone()LTest1; throws java/lang/CloneNotSupportedException 

public clone()Ljava/lang/Object; throws java/lang/CloneNotSupportedException 

แตกต่างกันตามประเภทการคืนสินค้าเท่านั้น


1
สิ่งนี้ทำให้เข้าใจผิดเนื่องจากวิธีการอินสแตนซ์มีอินสแตนซ์เป็นพารามิเตอร์แรกโดยปริยาย ครั้งหนึ่งอาจคิดว่า om (a) แท้จริงแล้ว m (o, a) ดังนั้นในกรณีของการโคลนสิ่งที่สร้างความแตกต่างคืออาร์กิวเมนต์ not return type
Huy Le


7

ใน JAVA และภาษาอื่น ๆ คุณสามารถเรียกใช้เมธอดโดยไม่ต้องใช้ตัวแปรเพื่อเก็บค่าส่งคืน หากชนิดการส่งคืนเป็นส่วนหนึ่งของลายเซ็นวิธีการไม่มีทางที่จะทราบได้ว่าจะเรียกใช้เมธอดใดเมื่อเรียกโดยไม่ระบุค่าที่ส่งคืนของตัวแปร


7

ข้อกำหนดภาษา Javaกล่าวว่า

สองวิธีมีลายเซ็นเหมือนกันหากมีชื่อและประเภทอาร์กิวเมนต์เดียวกัน

ดังนั้นไม่ประเภทการส่งคืนไม่ได้เป็นส่วนหนึ่งของลายเซ็นวิธีการ


4

Bro ใน java เราใช้เพื่อเรียกเมธอดตามชื่อและพารามิเตอร์เพื่อใช้ในโค้ดของเราเท่านั้นเช่น

myMethod (20, 40)

ดังนั้น JAVA จะค้นหาเฉพาะสิ่งที่คล้ายกันที่ตรงกันในการประกาศที่เกี่ยวข้อง (ชื่อ + พารามิเตอร์) นี่คือเหตุผลที่ลายเซ็นของวิธีการมีเฉพาะชื่อและพารามิเตอร์ของวิธีการเท่านั้น :)



3

ไม่ใน Java ลายเซ็นวิธีการไม่รวมประเภทการส่งคืน แต่การประกาศทำ

public             String         getString(String myString)

^access modifier   ^return type   ^name    ^parameter type and name

แก้ไขตามข้อเสนอแนะด้านล่าง :)


1
นั่นไม่ใช่สิ่งที่ JLS กล่าว มันคือ "ชื่อเดียวกันและประเภทอาร์กิวเมนต์" ตัวแก้ไขการเข้าถึงและชื่อพารามิเตอร์ไม่ได้เป็นส่วนหนึ่งของลายเซ็นวิธีการ
Peter Lawrey

ถ้าเป็นคำถามทดสอบก็ใช้ได้ แต่ถ้าฉันเขียนโปรแกรมฉันไม่ได้เขียน getString () สาธารณะฉันกำลังเขียน String getString () สาธารณะ
Jeff Hawthorne

1
ตัวแก้ไขการเข้าถึงประเภทการส่งคืนและประเภทการโยนไม่ได้เป็นส่วนหนึ่งของลายเซ็นซึ่งเป็นสาเหตุที่คุณไม่สามารถมีString method( String s )และDouble method( String s )อยู่ในคลาสเดียวกันได้
Ray Stojonic

2
บางทีคุณอาจสับสนmethod signatureกับmethod declaration
Peter Lawrey

@Ray ฉันต้องการทราบว่าฉันเขียนคำตอบของฉันก่อนที่เขาจะแก้ไขคำถามเริ่มต้นทั้งหมดที่เขาถามก็คือมันเป็นส่วนหนึ่งของลายเซ็นฉันต้องการให้แน่ใจว่าเขาไม่ได้พยายามเขียนชื่อสาธารณะ () โดยไม่แสดงรายการ ประเภทการส่งคืน (บอกความจริงเขาสามารถตอบคำถามของตัวเองได้เพียงแค่เขียนโปรแกรมง่ายๆเพื่อทดสอบ)
Jeff Hawthorne



1

ลายเซ็นวิธีการรวมถึงประเภทการคืนสินค้า

คอมไพลเลอร์จะละเว้นเมื่อต้องตรวจสอบรายการที่ซ้ำกัน สำหรับ Java นั้นผิดกฎหมายที่จะมีสองวิธีที่มีลายเซ็นแตกต่างกันตามชนิดการส่งคืนเท่านั้น

ลองดู:

public class Called {
    public String aMethod() {
        return "";
    }
}

public class Caller {
    public static void main(String[] main) {
        aMethod();
    }
    public static void aMethod() {
        Called x = new Called();
        x.aMethod();
    }
}

สร้างโครงการไปที่ไดเร็กทอรี bin คัดลอกCaller.cass ที่ใดที่หนึ่ง จากนั้นเปลี่ยนวิธีการที่เรียกว่า:

public int aMethod() {
    return 0;
}

สร้างโครงการคุณจะเห็นว่าทั้ง Calling.class และ Caller.class มีการประทับเวลาใหม่ แทนที่ Caller.class ด้านบนและเรียกใช้โครงการ คุณจะมีข้อยกเว้น:

java.lang.NoSuchMethodError: it.prova.Called.aMethod()Ljava/lang/String;

0

ลายเซ็นเมธอดเป็นเพียงชื่อและพารามิเตอร์ของเมธอดเท่านั้น แต่ฉันเชื่อว่าตัวอย่างของคุณจะสร้างข้อผิดพลาดหากพวกเขาอยู่ในคลาสเดียวกัน คุณสามารถทดสอบได้จาก ide ใด ๆ และดูว่าคอมไพเลอร์จะแสดงข้อผิดพลาด


0

หากคุณพยายามรันโค้ดที่คุณได้กล่าวถึงบน eclipse คุณจะมีคำตอบว่าองค์ประกอบใดที่คอมไพลเลอร์ java มองหาความแตกต่างระหว่างเมธอด java:

class Foo {
    public int  myMethod(int param) {
        return param;}
    public char *myMethod*(int param) { //this line throws an error 
        return param;
    }
}

ข้อผิดพลาดที่เกิดขึ้นคือ: วิธีการซ้ำ myMethod (int) ในประเภท Foo

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.