Apa tujuan dari kata kunci default di Java?

95

Antarmuka di Java mirip dengan kelas, tetapi tubuh antarmuka hanya dapat menyertakan metode dan finalbidang abstrak (konstanta).

Baru-baru ini, saya melihat sebuah pertanyaan, yang terlihat seperti ini

interface AnInterface {
    public default void myMethod() {
        System.out.println("D");
    }
}

Menurut definisi antarmuka, hanya metode abstrak yang diperbolehkan. Mengapa memungkinkan saya untuk mengkompilasi kode di atas? Apa defaultkata kuncinya?

Di sisi lain, ketika saya mencoba menulis kode di bawah ini, maka dikatakan modifier default not allowed here

default class MyClass{

}

dari pada

class MyClass {

}

Adakah yang bisa memberi tahu saya tujuan dari defaultkata kunci tersebut? Apakah hanya diperbolehkan di dalam antarmuka? Apa bedanya dengan default(tanpa pengubah akses)?

Ravi
sumber
4
metode default dalam antarmuka ditambahkan di Java 8. Ini bukan pengubah akses, ini adalah implementasi default.
Eran
2
@Eran tidakkah Anda berpikir, pengenalan metode default melanggar definisi antarmuka? : s
Ravi
2
Itu mengubah definisi antarmuka. Definisi itu sekarang sudah ketinggalan zaman.
Louis Wasserman
2
Mereka diperkenalkan untuk mendukung lambda. Rincian mengapa mereka diperlukan ada dalam proposal manusia jerami untuk Proyek Lambda.
sprinter

Jawaban:

75

Ini adalah fitur baru di Java 8 yang memungkinkan interfaceuntuk menyediakan implementasi. Dijelaskan di Java 8 JLS-13.5.6. Deklarasi Metode Antarmuka yang berbunyi (sebagian)

Menambahkan defaultmetode, atau mengubah metode dari abstractmenjadi default, tidak merusak kompatibilitas dengan biner yang sudah ada sebelumnya, tetapi dapat menyebabkan IncompatibleClassChangeErrorjika biner yang sudah ada mencoba untuk memanggil metode tersebut. Kesalahan ini terjadi jika jenis kualifikasi, T, adalah subtipe dari dua antarmuka, Idan J, di mana kedua Idan Jmenyatakan defaultmetode dengan tanda tangan yang sama dan hasilnya, dan tidakI juga Jadalah subinterface dari yang lain.

Yang Baru di JDK 8 mengatakan (sebagian)

Metode default memungkinkan fungsionalitas baru untuk ditambahkan ke antarmuka perpustakaan dan memastikan kompatibilitas biner dengan kode yang ditulis untuk versi lama dari antarmuka tersebut.

Elliott Frisch
sumber
16
Sepertinya, sekarang antarmuka dan kelas abstrak hampir sama. :)
Ravi
16
Antarmuka @jWeaver masih tidak dapat memiliki konstruktor, bidang, metode pribadi, atau implementasi yang sama / hashCode / toString.
Louis Wasserman
10
@Louis Wasserman: Di Java 9, mereka dapat memiliki privatemetode.
Holger
6
@Dan Pantry: privatemetode sebenarnya bukan bagian dari antarmuka, tetapi dapat berfungsi sebagai metode pembantu untuk defaultimplementasi atau dalam penginisialisasi konstan. Perhatikan bahwa mereka sudah ada di Java 8, karena, saat Anda menggunakan ekspresi lambda dalam antarmuka, privatemetode sintetis akan dibuat. Jadi Java 9 memungkinkan Anda menggunakan fitur itu untuk penggunaan non-sintetis, non lambda juga…
Holger
14
@jWeaver Perbedaan antara antarmuka dan kelas direduksi menjadi status vs perilaku . Antarmuka dapat membawa perilaku, tetapi hanya kelas yang dapat memiliki status. (Bidang, konstruktor, dan metode seperti equals / hashCode adalah tentang status.)
Brian Goetz
26

Metode default ditambahkan ke Java 8 terutama untuk mendukung ekspresi lambda. Para desainer (secara cerdik, dalam pandangan saya) memutuskan untuk membuat sintaks lambdas untuk membuat implementasi antarmuka tanpa nama. Tetapi mengingat lambda hanya dapat mengimplementasikan satu metode, mereka akan dibatasi pada antarmuka dengan metode tunggal yang akan menjadi batasan yang cukup parah. Sebaliknya, metode default ditambahkan untuk memungkinkan antarmuka yang lebih kompleks digunakan.

Jika Anda perlu meyakinkan klaim yang defaultdiperkenalkan karena lambda, perhatikan bahwa proposal manusia jerami Proyek Lambda, oleh Mark Reinhold, pada tahun 2009, menyebutkan 'Metode ekstensi' sebagai fitur wajib yang akan ditambahkan untuk mendukung lambda.

Berikut adalah contoh yang mendemonstrasikan konsep tersebut:

interface Operator {
    int operate(int n);
    default int inverse(int n) {
        return -operate(n);
    }
}

public int applyInverse(int n, Operator operator) {
    return operator.inverse(n);
}

applyInverse(3, n -> n * n + 7);

Sangat dibuat-buat saya menyadari tetapi harus menggambarkan bagaimana defaultmendukung lambda. Karena inversemerupakan default, ia dapat dengan mudah diganti oleh kelas pelaksana jika diperlukan.

pelari cepat
sumber
8
Ini tidak benar. Lambdas mungkin penyebab langsungnya, tetapi mereka sebenarnya hanyalah jerami yang mematahkan punggung unta. Motivasi sebenarnya adalah memungkinkan evolusi antarmuka (memungkinkan antarmuka yang ada berevolusi secara kompatibel untuk mendukung perilaku baru); lambda mungkin menjadi faktor yang membawa kebutuhan ini ke depan, tetapi fiturnya lebih umum dari itu.
Brian Goetz
@BrianGoetz: IMHO, baik Java dan .NET akan mendapatkan keuntungan yang sangat besar jika metode default sudah ada sejak awal. Jika beberapa operasi umum dapat dilakukan pada implementasi antarmuka apa pun yang hanya menggunakan anggota antarmuka, tetapi beberapa implementasi mungkin memiliki cara yang lebih efisien untuk melakukannya, antarmuka harus menentukan metode untuk operasi tersebut dan menyediakan implementasi default untuknya. Ketidakmampuan untuk menentukan implementasi default telah menyebabkan tekanan agar antarmuka mengabaikan metode tersebut, dan membuatnya tidak mungkin untuk ditambahkan nanti.
supercat
@ BrianGoetz Saya setuju metode default memiliki nilai signifikan di luar lambda. Tapi saya tertarik dengan referensi apa pun yang dapat Anda berikan untuk nilai yang lebih luas yang mendorong keputusan untuk menyertakannya. Saya membaca bahwa lambda adalah alasan utama (itulah sebabnya saya menggunakan kata 'terutama' dalam jawaban saya).
sprinter
2
Mungkin dokumen ini akan membantu: cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html . Bagian 10 menjelaskan dengan jelas: "Tujuan dari metode default (sebelumnya disebut sebagai metode ekstensi virtual atau metode pembela) adalah untuk memungkinkan antarmuka dikembangkan dengan cara yang kompatibel setelah publikasi awal mereka." Metode ramah Lambda kemudian dikutip sebagai ilustrasi evolusi antarmuka.
Brian Goetz
2
@Kartik Anda menanyakan pertanyaan yang salah! Kami tidak memilih sintaks berdasarkan "apa yang merupakan minimum absolut yang diperlukan kompilator untuk mengurai program dengan benar"; kami memilihnya atas dasar "apa yang akan membuat maksud pemrogram lebih langsung terlihat jelas bagi pembaca". Kami merancang pertama untuk pengguna, dan kedua untuk kompiler (dan ketika datang ke pengguna, kami merancang pertama untuk membaca, dan kedua untuk menulis.)
Brian Goetz
16

Konsep baru diperkenalkan di Java 8 yang disebut metode default. Metode default adalah metode yang memiliki beberapa implementasi default dan membantu dalam mengembangkan antarmuka tanpa merusak kode yang ada. Mari kita lihat contohnya:

 public interface SimpleInterface {
    public void doSomeWork();

    //A default method in the interface created using "default" keyword

    default public void doSomeOtherWork(){

    System.out.println("DoSomeOtherWork implementation in the interface");
       }
    }

 class SimpleInterfaceImpl implements SimpleInterface{

  @Override
  public void doSomeWork() {
  System.out.println("Do Some Work implementation in the class");
   }

 /*
  * Not required to override to provide an implementation
  * for doSomeOtherWork.
  */

 public static void main(String[] args) {
   SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
   simpObj.doSomeWork();
   simpObj.doSomeOtherWork();
      }
   }

dan hasilnya adalah:

Do Some Work implementasi di kelas
DoSomeOtherWork implementasi di antarmuka

Saurabh Gaur
sumber
16

Sesuatu yang terlewatkan dalam jawaban lain adalah perannya dalam anotasi. Sejauh Java 1.5, defaultkata kunci muncul sebagai sarana untuk memberikan nilai default untuk bidang anotasi.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Processor {
    String value() default "AMD";
}

Penggunaannya kelebihan beban dengan diperkenalkannya Java 8 untuk memungkinkan seseorang menentukan metode default dalam antarmuka.

Hal lain yang terlewatkan: alasan deklarasi default class MyClass {}tersebut tidak valid adalah karena cara kelas dideklarasikan sama sekali . Tidak ada ketentuan dalam bahasa yang memungkinkan kata kunci tersebut muncul di sana. Itu memang muncul untuk deklarasi metode antarmuka .

Makoto
sumber
3

Fitur baru Java 8 ( Metode Default ) memungkinkan sebuah antarmuka menyediakan implementasi ketika diberi label dengan defaultkata kunci.

Sebagai contoh:

interface Test {
    default double getAvg(int avg) {
        return avg;
    }
}
class Tester implements Test{
 //compiles just fine
}

Uji Antarmuka menggunakan kata kunci default yang memungkinkan antarmuka menyediakan implementasi default metode tanpa perlu menerapkan metode tersebut di kelas yang menggunakan antarmuka.

Kompatibilitas terbalik: Bayangkan antarmuka Anda diimplementasikan oleh ratusan kelas, mengubah antarmuka itu akan memaksa semua pengguna untuk mengimplementasikan metode yang baru ditambahkan, meskipun itu tidak penting untuk banyak kelas lain yang mengimplementasikan antarmuka Anda.

Fakta & Batasan:

1-Mei hanya dideklarasikan dalam antarmuka dan tidak dalam kelas atau kelas abstrak.

2-Harus menyediakan tubuh

3-Ini tidak dianggap publik atau abstrak seperti metode normal lainnya yang digunakan dalam sebuah antarmuka.

Ahmad Sanie
sumber
3

Metode default di antarmuka memungkinkan kita menambahkan fungsionalitas baru tanpa merusak kode lama.

Sebelum Java 8, jika metode baru ditambahkan ke antarmuka, maka semua kelas implementasi antarmuka itu terikat untuk mengganti metode baru itu, bahkan jika mereka tidak menggunakan fungsionalitas baru.

Dengan Java 8, kita bisa menambahkan implementasi default untuk metode baru dengan menggunakan default kata kunci sebelum implementasi metode.

Bahkan dengan kelas anonim atau antarmuka fungsional, jika kita melihat bahwa beberapa kode dapat digunakan kembali dan kita tidak ingin mendefinisikan logika yang sama di mana pun dalam kode, kita dapat menulis implementasi default dari kode tersebut dan menggunakannya kembali.

Contoh

public interface YourInterface {
    public void doSomeWork();

    //A default method in the interface created using "default" keyword
    default public void doSomeOtherWork(){

    System.out.println("DoSomeOtherWork implementation in the interface");
       }
    }

    class SimpleInterfaceImpl implements YourInterface{

     /*
     * Not required to override to provide an implementation
     * for doSomeOtherWork.
     */
      @Override
      public void doSomeWork() {
  System.out.println("Do Some Work implementation in the class");
   }

 /*
  * Main method
  */
 public static void main(String[] args) {
   SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
   simpObj.doSomeWork();
   simpObj.doSomeOtherWork();
      }
   }
Dickson sang pengembang
sumber
2

Penjelasan yang sangat bagus ditemukan di The Java ™ Tutorials , bagian dari penjelasannya adalah sebagai berikut:

Pertimbangkan contoh yang melibatkan produsen mobil yang dikendalikan komputer yang menerbitkan antarmuka standar industri yang menjelaskan metode mana yang dapat digunakan untuk mengoperasikan mobil mereka. Bagaimana jika produsen mobil yang dikendalikan komputer tersebut menambahkan fungsi baru, seperti penerbangan, ke mobil mereka? Pabrikan ini perlu menentukan metode baru untuk memungkinkan perusahaan lain (seperti pabrikan instrumen panduan elektronik) untuk menyesuaikan perangkat lunak mereka dengan mobil terbang. Di mana produsen mobil ini akan mengumumkan metode terkait penerbangan baru ini? Jika mereka menambahkannya ke antarmuka aslinya, maka programmer yang telah mengimplementasikan antarmuka tersebut harus menulis ulang implementasinya. Jika mereka menambahkannya sebagai metode statis, maka programmer akan menganggapnya sebagai metode utilitas, bukan metode inti yang esensial.

Metode default memungkinkan Anda menambahkan fungsionalitas baru ke antarmuka pustaka Anda dan memastikan kompatibilitas biner dengan kode yang ditulis untuk versi lama antarmuka tersebut.

Riyafa Abdul Hameed
sumber
1

Metode default memungkinkan Anda menambahkan fungsionalitas baru ke antarmuka aplikasi Anda. Ini juga dapat digunakan untuk memiliki multi warisan . Selain metode default, Anda dapat menentukan metode statis di antarmuka. Ini memudahkan Anda untuk mengatur metode pembantu

pengguna3359139
sumber