Argumen terakhir dalam metode antarmuka - apa gunanya?

189

Di Jawa, sangat sah untuk mendefinisikan finalargumen dalam metode antarmuka dan tidak mematuhinya dalam kelas implementasi, misalnya:

public interface Foo {
    public void foo(int bar, final int baz);
}

public class FooImpl implements Foo {

    @Override
    public void foo(final int bar, int baz) {
        ...
    }
}

Dalam contoh di atas, bardan bazmemiliki finaldefinisi yang berlawanan di kelas VS antarmuka.

Dengan cara yang sama, tidak ada finalbatasan yang diberlakukan ketika satu metode kelas memperluas yang lain, baik abstractatau tidak.

Meskipun finalmemiliki beberapa nilai praktis di dalam tubuh metode kelas, apakah ada titik yang menentukan finalparameter metode antarmuka?

mindas
sumber
finaltidak melakukan apa pun dengan tipe asli, karena mereka disalin
Paul Tomblin
11
Sama seperti titik diskusi: Saya baru saja mencobanya dan jika dua interfacedefinisi hanya berbeda dalam finalatribut argumen, maka .classfile yang dihasilkan adalah byte-untuk-byte yang identik (dan tentu saja javap -vmenghasilkan output yang sama). Hal yang sama berlaku untuk dua kelas yang hanya berbeda finalpada satu atribut, omong-omong!
Joachim Sauer
2
@ Paul: ia melakukan hal yang persis sama dengan jenis referensi: itu mencegah argumen itu sendiri untuk dimodifikasi (jika digunakan dalam implementasi).
Joachim Sauer
Ini memiliki relevansi sebanyak publik dalam metode tanda tangan.
Robin
2
@Deepak: Saya melihat Anda meminta contoh untuk mengerjakan semua jenis pertanyaan, bahkan ketika itu tampaknya tidak masuk akal. Saya pikir Anda harus mencoba belajar beberapa pemikiran abstrak: coba pikirkan masalah tanpa memiliki kode yang dapat dieksekusi di depan Anda. Ini akan banyak membantu Anda dalam jangka panjang.
Joachim Sauer

Jawaban:

104

Sepertinya tidak ada gunanya. Menurut Spesifikasi Bahasa Jawa 4.12.4 :

Mendeklarasikan variabel final dapat berfungsi sebagai dokumentasi yang bermanfaat bahwa nilainya tidak akan berubah dan dapat membantu menghindari kesalahan pemrograman.

Namun, finalpengubah pada parameter metode tidak disebutkan dalam aturan untuk mencocokkan tanda tangan metode yang diganti, dan itu tidak berpengaruh pada pemanggil, hanya dalam tubuh implementasi. Juga, seperti dicatat oleh Robin dalam komentar, finalpengubah pada parameter metode tidak berpengaruh pada kode byte yang dihasilkan. (Ini tidak benar untuk penggunaan lain dari final.)

Ted Hopp
sumber
Apakah parameter metode juga memenuhi syarat sebagai variabel? Jelas dalam praktiknya, tetapi apakah itu dalam konteks spesifikasi?
mindas
11
Itu tidak dapat digunakan untuk mencocokkan tanda tangan karena tidak muncul dalam file .class yang sebenarnya. Ini hanya untuk kompiler.
Robin
@mindas - JLS mengatakan bahwa ada tujuh jenis variabel . Paramaters metode keempat dalam daftar.
Ted Hopp
3
Dokumentasi hampir tidak berguna, karena finalpengubah tidak diberlakukan pada kelas pelaksana. Tanda tangan antarmuka Anda mungkin berbohong.
Stefan Haberl
Spesifikasi bahasa Java 8 sekarang mengatakan bahwa ada delapan jenis variabel (naik dari tujuh - mereka menambahkan parameter lambda ). Parameter metode masih keempat dalam daftar (setidaknya beberapa hal dalam hidup tampak stabil. :-)).
Ted Hopp
25

Beberapa IDE akan menyalin tanda tangan dari metode abstrak / antarmuka saat memasukkan metode implementasi di sub kelas.

Saya tidak percaya ada bedanya dengan kompiler.

EDIT: Sementara saya percaya ini benar di masa lalu, saya tidak berpikir IDE saat ini melakukan ini lagi.

Peter Lawrey
sumber
2
Poin yang benar, meskipun saya tidak berpikir ada banyak IDE ketika fitur ini diimplementasikan (atau dibiarkan tidak sengaja) :-)
mindas
2
Saya pikir dalam kategori static transientbidang. ;)
Peter Lawrey
1
Dan konstruktor publik pada kelas abstrak.
Peter Lawrey
1
IntelliJ melakukan ini. Versi saya adalah IntelliJ IDEA 2016.1.3 Build # IU-145.1617.
Asrama
1
@Douse, ini menarik, karena Android Studio (3.1.4 Build # AI-173.4907809) tidak :(
The Godfather
18

Anotasi akhir parameter metode selalu hanya relevan dengan implementasi metode tidak pernah ke pemanggil. Oleh karena itu, tidak ada alasan nyata untuk menggunakannya dalam tanda tangan metode antarmuka. Kecuali jika Anda ingin mengikuti standar pengkodean yang konsisten yang sama, yang membutuhkan parameter metode akhir, di semua tanda tangan metode. Maka itu bagus untuk dapat melakukannya.

jmg
sumber
6

Pembaruan: Jawaban asli di bawah ditulis tanpa sepenuhnya memahami pertanyaan, dan karena itu tidak secara langsung menjawab pertanyaan tersebut. :)Namun, itu harus informatif bagi mereka yang ingin memahami penggunaan finalkata kunci secara umum .

Adapun pertanyaannya, saya ingin mengutip komentar saya sendiri dari bawah.

Saya percaya Anda tidak dipaksa untuk mengimplementasikan finalitas argumen agar Anda bebas memutuskan apakah itu final atau tidak dalam implementasi Anda sendiri.

Tapi ya, kedengarannya agak aneh bahwa Anda dapat mendeklarasikannya finaldi antarmuka, tetapi memilikinya non-final dalam implementasi. Akan lebih masuk akal jika:

Sebuah. finalkata kunci tidak diizinkan untuk argumen metode antarmuka (abstrak) (tetapi Anda dapat menggunakannya dalam implementasi), atau
b. mendeklarasikan argumen seperti finalpada antarmuka akan memaksanya dinyatakan finaldalam implementasi (tetapi tidak dipaksakan untuk non-final).


Saya dapat memikirkan dua alasan mengapa metode tanda tangan dapat memiliki finalparameter: Kacang dan Objek ( Sebenarnya, keduanya adalah alasan yang sama, tetapi konteks yang sedikit berbeda. )

Benda:

public static void main(String[] args) {
    StringBuilder cookingPot = new StringBuilder("Water ");
    addVegetables(cookingPot);
    addChicken(cookingPot);
    System.out.println(cookingPot.toString());
    // ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth 
    //      We forgot to add cauliflower. It went into the wrong pot.
}

private static void addVegetables(StringBuilder cookingPot) {
    cookingPot.append("Carrot ");
    cookingPot.append("Broccoli ");
    cookingPot = new StringBuilder(cookingPot.toString());
    //   ^--- Assignment allowed...
    cookingPot.append("Cauliflower ");
}

private static void addChicken(final StringBuilder cookingPot) {
    cookingPot.append("Chicken ");
    //cookingPot = new StringBuilder(cookingPot.toString());
    //     ^---- COMPILATION ERROR! It is final.
    cookingPot.append("ChickenBroth ");
}

Kata finalkunci memastikan bahwa kami tidak akan secara tidak sengaja membuat panci memasak lokal baru dengan menunjukkan kesalahan kompilasi ketika kami berusaha melakukannya. Ini memastikan kaldu ayam ditambahkan ke panci masak asli kami yang addChickenmetodenya didapat. Bandingkan ini dengan addVegetablestempat kami kehilangan kembang kol karena menambahkan bahwa ke panci memasak lokal baru, bukan pot asli yang didapat.

Kacang: Ini adalah konsep yang sama dengan objek (seperti yang ditunjukkan di atas) . Kacang pada dasarnya ada Objectdi Jawa. Namun, kacang (JavaBeans) digunakan dalam berbagai aplikasi sebagai cara mudah untuk menyimpan dan menyebarkan koleksi data terkait yang telah ditentukan. Sama seperti yang addVegetablesbisa mengacaukan proses memasak dengan membuat panci memasak baru StringBuilderdan membuangnya bersama kembang kol, itu juga bisa melakukan hal yang sama dengan panci memasak JavaBean .

ADTC
sumber
Baik. Ini sebenarnya bukan jawaban yang benar untuk pertanyaan, (karena saya tidak dipaksa untuk membuat implementasi metode antarmuka saya mengambil argumen akhir, bahkan jika antarmuka mengatakan demikian), tapi itu masih membantu, karena itu penjelasan yang bagus mengapa membuat parameter metode akhir adalah ide yang baik untuk memulai.
Phil
Saya percaya Anda tidak dipaksa untuk mengimplementasikan finalitas argumen agar Anda bebas memutuskan apakah itu final atau tidak dalam implementasi Anda sendiri. Tapi ya, kedengarannya agak aneh bahwa Anda dapat mendeklarasikannya finaldi antarmuka, tetapi memilikinya non-final dalam implementasi. Akan lebih masuk akal jika salah satu (a) final kata kunci tidak diizinkan untuk argumen metode antarmuka (abstrak) (tetapi Anda dapat menggunakannya dalam implementasi), atau (b) mendeklarasikan argumen karena finaldi antarmuka akan memaksanya untuk dinyatakan finaldalam implementasi (tetapi tidak dipaksa untuk non-final).
ADTC
"Itu bukan jawaban yang benar untuk pertanyaan," Kamu benar, aku tidak tahu apa yang kupikirkan ... pasti awal Juli atau sesuatu. :)
ADTC
2

Saya percaya itu mungkin detail yang berlebihan, apakah itu final atau tidak adalah detail implementasi.

(Semacam suka menyatakan metode / anggota dalam antarmuka sebagai publik.)

Peter
sumber