CodeGym /Blog Java /rawak /Kaedah dalam Java
John Squirrels
Tahap
San Francisco

Kaedah dalam Java

Diterbitkan dalam kumpulan
Hello lagi! Dalam pelajaran lepas kami berkenalan dengan kelas dan pembina, dan belajar cara mencipta kelas kami sendiri. Hari ini kita akan lebih mengenali Kaedah Java, bahagian penting dalam kelas. Kaedah dalam Java ialah satu set arahan yang membolehkan anda melakukan operasi tertentu dalam program. Dengan kata lain, kaedah adalah fungsi; sesuatu yang kelas anda mampu lakukan. Dalam bahasa pengaturcaraan lain, kaedah sering dipanggil "fungsi", tetapi dalam Java perkataan "kaedah" lebih biasa. :) Jika anda masih ingat, dalam pelajaran lepas kami mencipta kaedah mudah untuk kelas Kucing , supaya kucing kami boleh menyebut meow dan melompat:

public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Pounce!");
    }

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        smudge.sayMeow();
        smudge.jump();
    }
}
sayMeow() dan jump() ialah kaedah kelas kami. Dan menjalankan kaedah ini menghasilkan output konsol berikut:
Meow!
Pounce!
Kaedah kami agak mudah: mereka hanya mengeluarkan teks ke konsol. Tetapi di Jawa, kaedah mempunyai tugas penting: mereka melakukan tindakan pada data objek. Mereka menukar data objek, mengubahnya, memaparkannya dan melakukan perkara lain dengannya. Kaedah semasa kami tidak melakukan apa-apa dengan data objek Cat . Mari kita lihat contoh yang lebih ilustrasi:

public class Truck {

    int length;
    int width;
    int height;
    int weight;

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
Sebagai contoh, di sini kita mempunyai kelas yang mewakili Lori . Trak separuh mempunyai panjang, lebar, tinggi dan berat (yang kita perlukan kemudian). Dalam kaedah getVolume() , kami melakukan pengiraan, menukar data objek kami kepada nombor yang mewakili volumnya (kami mendarabkan panjang, lebar dan tinggi). Nombor ini akan menjadi hasil kaedah. Ambil perhatian bahawa pengisytiharan kaedah ditulis sebagai public int getVolume . Ini bermakna bahawa kaedah ini mesti mengembalikan int . Kami mengira nilai pulangan kaedah, dan kini kami mesti mengembalikannya kepada program yang memanggil kaedah kami. Untuk mengembalikan hasil kaedah dalam Java, kami menggunakan pulangan kata kunci. jumlah pulangan;

Parameter Kaedah Java

Kita boleh menghantar nilai yang dipanggil "argumen" kepada kaedah apabila memanggilnya. Pengisytiharan kaedah termasuk senarai pembolehubah yang memberitahu kami jenis dan susunan pembolehubah yang kaedah boleh terima. Senarai ini dipanggil "parameter kaedah". Kaedah getVolume() kelas Truck kami tidak mentakrifkan sebarang parameter pada masa ini, jadi mari cuba lanjutkan contoh trak kami. Buat kelas baharu yang dipanggil BridgeOfficer . Ini adalah pegawai polis yang bertugas di sebuah jambatan, yang memeriksa semua trak yang lalu untuk melihat sama ada muatannya melebihi berat yang dibenarkan.

public class BridgeOfficer {

    int maxWeight;

    public BridgeOfficer(int normalWeight) {
        this.maxWeight = normalWeight;
    }

    public boolean checkTruck(Truck truck) {
        if (truck.weight > maxWeight) {
            return false;
        } else {
            return true;
        }
    }
}
Kaedah checkTruck menerima satu hujah, objek Trak , dan menentukan sama ada pegawai itu akan membenarkan trak di atas jambatan atau tidak. Di dalam kaedah, logiknya cukup mudah: jika berat trak melebihi maksimum yang dibenarkan, maka kaedah itu mengembalikan palsu . Ia perlu mencari jalan lain :( Jika berat kurang daripada atau sama dengan maksimum, ia boleh lulus, dan kaedah itu kembali benar. Jika anda belum memahami sepenuhnya frasa "kembali" atau "kaedah mengembalikan nilai", mari berehat daripada pengaturcaraan dan pertimbangkan mereka menggunakan contoh mudah daripada kehidupan sebenar. :) Katakan anda jatuh sakit dan tinggal di rumah dari kerja selama beberapa hari. Anda pergi ke bahagian perakaunan dengan membawa nota doktor anda, kerana cuti sakit sepatutnya dibayar. Jika kita membandingkan keadaan ini dengan kaedah, maka akauntan mempunyai paySickLeave ()kaedah. Anda lulus nota doktor sebagai hujah kepada kaedah ini (tanpanya, kaedah itu tidak akan berfungsi dan anda tidak akan dibayar!). Kemudian pengiraan yang diperlukan dibuat di dalam kaedah menggunakan nota anda (akaun menggunakannya untuk mengira jumlah yang perlu dibayar oleh syarikat kepada anda), dan hasil kerja anda (sejumlah wang) dikembalikan kepada anda. Program kami berfungsi dengan cara yang sama. Ia memanggil kaedah, menghantar data kepadanya, dan akhirnya menerima hasil. Berikut ialah kaedah main() program BridgeOfficer kami:

public static void main(String[] args) {
    Truck first = new Truck();
    first.weight = 10000;
    Truck second = new Truck();
    second.weight = 20000;

    BridgeOfficer officer = new BridgeOfficer(15000);
    System.out.println("Truck 1! Can I go, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck 2! And can I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
Kami mencipta dua trak dengan muatan 10,000 dan 20,000. Dan jambatan tempat pegawai bekerja mempunyai berat maksimum 15,000. Program ini memanggil kaedah pegawai.checkTruck(first) . Kaedah ini mengira segala-galanya dan kemudian mengembalikan true , yang kemudiannya disimpan oleh program dalam pembolehubah boolean canFirstTruckGo . Kini anda boleh melakukan apa sahaja yang anda mahu dengannya (sama seperti anda boleh dengan wang yang diberikan oleh akauntan kepada anda). Pada penghujung hari, kod

boolean canFirstTruckGo = officer.checkTruck(first);
bermuara kepada

boolean canFirstTruckGo =  true;
Inilah perkara yang sangat penting: penyata pulangan bukan sahaja mengembalikan nilai pulangan kaedah, ia juga menghentikan kaedah daripada berjalan! Sebarang kod yang datang selepas penyata pemulangan tidak akan dilaksanakan!

public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, you're overweight!");
    } else {
        return true;
        System.out.println("Everything looks good, go ahead!");
    }
}
Komen pegawai tidak akan dipaparkan, kerana kaedah itu telah mengembalikan keputusan dan ditamatkan! Program kembali ke tempat di mana kaedah itu dipanggil. Anda tidak perlu memerhatikan perkara ini: pengkompil Java cukup bijak untuk menjana ralat apabila anda cuba menulis kod selepas penyataan pulangan .

Avengers: Perang Parameter

Terdapat situasi apabila kita memerlukan beberapa cara untuk memanggil kaedah. Mengapa tidak mencipta kecerdasan buatan kita sendiri? Amazon mempunyai Alexa, Apple mempunyai Siri, jadi mengapa kita tidak perlu memilikinya? :) Dalam filem Iron Man, Tony Stark mencipta kecerdasan buatannya yang luar biasa, Jarvis. Mari kita beri penghormatan kepada watak hebat itu dan namakan AI kita sebagai penghormatan kepadanya. :) Perkara pertama yang perlu kita lakukan ialah mengajar Jarvis untuk bertanya khabar kepada orang yang memasuki bilik (alangkah peliknya jika intelek yang luar biasa itu ternyata tidak sopan).

public class Jarvis {

    public void sayHi(String name) {
        System.out.println("Good evening, " + name + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
    }
}
Output konsol:
Good evening, Tony Stark. How are you?
Sangat bagus! Jarvis kini boleh menyambut tetamu. Sudah tentu, lebih kerap daripada tidak ia akan menjadi tuannya, Tony Stark. Tetapi bagaimana jika dia tidak datang sendiri! Kaedah sayHi() kami hanya menerima satu hujah. Jadi ia hanya boleh menyambut seorang yang memasuki bilik, dan akan mengabaikan yang lain. Tidak sangat sopan, tidakkah anda bersetuju? :/

Kaedah Java Overloading

Dalam kes ini, kita boleh menyelesaikan masalah dengan hanya menulis 2 kaedah dengan nama yang sama, tetapi parameter yang berbeza:

public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }
}
Ini dipanggil kaedah overloading. Kaedah lebihan beban membolehkan program kami menjadi lebih fleksibel dan menampung pelbagai cara kerja. Mari kita semak cara ia berfungsi:

public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
        jarvis.sayHi("Tony Stark", "Captain America");
    }
}
Output konsol:
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
Hebat, kedua-dua versi berfungsi. :) Tetapi kami tidak menyelesaikan masalah! Bagaimana jika ada tiga tetamu? Kami boleh, sudah tentu, membebankan kaedah sayHi() sekali lagi, supaya ia menerima tiga nama tetamu. Tetapi mungkin ada 4 atau 5. Sepanjang jalan ke infiniti. Tidakkah terdapat cara yang lebih baik untuk mengajar Jarvis mengendalikan sebarang bilangan nama, tanpa membebankan kaedah sayHi() sejuta kali? :/ Sudah tentu ada! Jika tiada, adakah anda fikir Java akan menjadi bahasa pengaturcaraan paling popular di dunia? ;)

public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ". How are you?");
    }
}
Apabila ( String... names ) digunakan sebagai parameter, ia menunjukkan bahawa koleksi String akan dihantar kepada kaedah. Kami tidak perlu menyatakan terlebih dahulu berapa banyak yang akan ada, jadi sekarang kaedah kami adalah lebih fleksibel:

public class Jarvis {

    public void sayHi(String...names) {
        for (String name: names) {
            System.out.println("Good evening, " + name + ". How are you?");
        }
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
    }
}
Output konsol:
Good evening, Tony Stark. How are you?
Good evening, Captain America. How are you?
Good evening, Black Widow. How are you?
Good evening, Hulk. How are you?
Sesetengah kod di sini akan menjadi asing kepada anda, tetapi jangan risau tentangnya. Ia mudah pada terasnya: kaedah mengambil setiap nama secara bergilir-gilir dan menyambut setiap tetamu! Selain itu, ia akan berfungsi dengan sebarang bilangan rentetan yang diluluskan! Dua, sepuluh, malah seribu—kaedah ini akan berfungsi dengan baik dengan sebarang bilangan tetamu. Jauh lebih mudah daripada membebankan kaedah untuk semua kemungkinan, bukankah anda fikir? :) Ini satu lagi perkara penting: susunan hujah itu penting! Katakan kaedah kami mengambil String dan nombor:

public class Person {

    public static void sayYourAge(String greeting, int age) {
        System.out.println(greeting + " " + age);
    }

    public static void main(String[] args) {
        sayYourAge("My age is ", 33);
        sayYourAge(33, "My age is "); // Error!
    }
}
Jika kaedah sayYourAge kelas Person mengambil rentetan dan nombor sebagai input, maka program mesti menghantarnya dalam susunan khusus itu! Jika kita menghantarnya dalam susunan yang berbeza, pengkompil akan menghasilkan ralat dan orang itu tidak akan dapat menyatakan umurnya. Dengan cara ini, pembina, yang kami bincangkan dalam pelajaran lepas, juga merupakan kaedah! Anda juga boleh membebankannya (iaitu mencipta beberapa pembina dengan set parameter yang berbeza) dan susunan hujah yang diluluskan pada asasnya penting untuk mereka juga. Mereka kaedah sebenar! :)

Sekali lagi mengenai parameter

Ya, maaf, kami belum selesai dengan mereka. :) Topik yang akan kita pelajari sekarang adalah sangat penting. Terdapat 90% kemungkinan anda akan ditanya tentang perkara ini pada setiap temuduga akan datang! Mari kita bercakap tentang menyampaikan hujah kepada kaedah. Pertimbangkan contoh mudah:

public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        currentYear = currentYear-10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What year is it?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("How about now?");
        System.out.println(currentYear);
    }
}
Mesin masa mempunyai dua kaedah. Kedua-duanya mengambil nombor yang mewakili tahun semasa sebagai input, dan sama ada meningkatkan atau menurunkan nilainya (bergantung pada sama ada kita mahu pergi ke masa lalu atau masa depan). Tetapi, seperti yang anda lihat dari output konsol, kaedah itu tidak berfungsi! Output konsol:
What year is it?
2018
How about now?
2018
Kami menyerahkan pembolehubah currentYear kepada kaedah goToPast() , tetapi nilainya tidak berubah. Kami berada pada tahun 2018, dan di sini kami telah tinggal. Tapi kenapa? :/ Kerana primitif dalam Java dihantar kepada kaedah mengikut nilai. Apakah maksudnya? Apabila kita memanggil kaedah goToPast() dan menyerahkan pembolehubah int currentYear (=2018) kepadanya, kaedah tersebut tidak mendapat pembolehubah currentYear itu sendiri, sebaliknya salinannya. Sudah tentu, nilai salinan ini juga adalah 2018, tetapi sebarang perubahan pada salinan tidak menjejaskan pembolehubah tahun semasa asal kami dalam apa jua cara! Mari jadikan kod kami lebih jelas dan lihat apa yang berlaku dengan currentYear:

public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        System.out.println("The goToPast method has started running!");
        System.out.println("currentYear inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("currentYear inside the goToPast method (at the end) = " + currentYear);
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What was the year when the program started?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And what year is it now?");
        System.out.println(currentYear);
    }
}
Output konsol:
What was the year when the program started?
2018
The goToPast method has started running!
currentYear inside the goToPast method (at the beginning) = 2018
currentYear inside the goToPast method (at the end) = 2008
And what year is it now?
2018
Ini jelas menunjukkan bahawa pembolehubah yang dihantar kepada kaedah goToPast() hanyalah salinan currentYear . Dan menukar salinan tidak menjejaskan nilai "asal". "Lulus dengan rujukan" bermaksud sebaliknya. Jom amalkan kucing! Maksud saya, mari kita lihat bagaimana rujukan lewat menggunakan contoh kucing. :)

public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Kini dengan bantuan mesin masa kami, kami akan menghantar Smudge , kucing pengembara masa pertama di dunia, ke masa lalu dan masa depan! Mari kita ubah suai kelas TimeMachine supaya ia berfungsi dengan objek Cat ;

public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }    
}
Sekarang kaedah tidak hanya menukar nombor yang diluluskan. Sebaliknya, mereka menukar medan umur Kucing tertentu itu . Anda akan ingat bahawa ini tidak berfungsi untuk kami dengan primitif, kerana nombor asal tidak berubah. Mari lihat apa yang akan berlaku!

public static void main(String[] args) {

    TimeMachine timeMachine = new TimeMachine();
    Cat smudge = new Cat(5);

    System.out.println("How old was Smudge when the program started?");
    System.out.println(smudge.age);

    timeMachine.goToFuture(smudge);
    System.out.println("How about now?");
    System.out.println(smudge.age);

    System.out.println("Holy smokes! Smudge has aged 10 years! Back up quickly!");
    timeMachine.goToPast(smudge);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(smudge.age);
}
Output konsol:
How old was Smudge when the program started running?
5
How about now?
15
Holy smokes! Smudge has aged 10 years! Back up quickly!
Did it work? Have we returned the cat to its original age?
5
Wah! Sekarang kaedah itu melakukan sesuatu yang berbeza: kucing kami berumur secara drastik, tetapi kemudian ia menjadi muda semula! :) Mari cuba fikirkan sebabnya. Berbeza dengan contoh dengan primitif, apabila objek dihantar ke kaedah ia diluluskan melalui rujukan. Rujukan kepada objek smudge asal telah dihantar kepada kaedah changeAge() . Jadi, apabila kita menukar smudge.age dalam kaedah, kita merujuk kawasan memori yang sama di mana objek kita disimpan. Ia merujuk kepada Smudge yang sama yang kami buat pada mulanya. Ini dipanggil "laluan dengan rujukan"! Walau bagaimanapun, tidak semua yang mempunyai rujukan semudah itu. :) Mari cuba ubah contoh kita:

public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat = new Cat(cat.age);
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat = new Cat(cat.age);
        cat.age -= 10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        Cat smudge = new Cat(5);

        System.out.println("How old was Smudge when the program started?");
        System.out.println(smudge.age);

        timeMachine.goToFuture(smudge);
        System.out.println ("Smudge went to the future! Has his age changed?");
        System.out.println(smudge.age);

        System.out.println ("And if you try going back?");
        timeMachine.goToPast(smudge);
        System.out.println(smudge.age);
    }
}
Output konsol:
How old was Smudge when the program started running?
5
Smudge went to the future! Has his age changed?
5
And if you try going back?
5
Ia tidak berfungsi lagi! О_О Mari kita fikirkan apa yang berlaku. :) Ia mempunyai kaitan dengan kaedah goToPast / goToFuture dan cara rujukan berfungsi. Sekarang, perhatian anda, sila! Ini adalah perkara yang paling penting untuk difahami tentang cara rujukan dan kaedah berfungsi. Hakikatnya, apabila kita memanggil kaedah goToFuture(Cat cat) , ia adalah salinan rujukan kepada objek kucing yang diluluskan, bukan rujukan itu sendiri. Oleh itu, apabila kita menghantar objek kepada kaedah, terdapat dua rujukan kepada objek. Ini sangat penting untuk memahami apa yang berlaku. Inilah sebabnya mengapa umur kucing tidak berubah dalam contoh terakhir kami. Dalam contoh sebelumnya, apabila menukar umur, kami hanya mengambil rujukan yang diserahkan kepada goToFuture()kaedah, dan menggunakannya untuk mencari objek dalam ingatan dan menukar umurnya ( cat.age += 10 ). Tetapi sekarang, dalam kaedah goToFuture() , kami sedang mencipta objek baharu ( cat = new Cat(cat.age) ), dan objek ini diberikan salinan rujukan yang sama yang telah dihantar kepada kaedah tersebut. Akibatnya:
  • Rujukan pertama ( Cat smudge = New Cat (5) ) menunjuk kepada kucing asal (dengan umur 5)
  • Selepas itu, apabila kami lulus pembolehubah kucing kaedah goToPast() dan memberikannya objek baharu, rujukan telah disalin.
Dan ini membawa kita kepada hasil akhir: dua rujukan menunjuk kepada dua objek berbeza. Tetapi kami hanya mengubah umur salah seorang daripada mereka (yang dicipta di dalam kaedah).

cat.age += 10;
Dan sudah tentu, dalam kaedah main() kita dapat melihat pada konsol bahawa umur kucing, smudge.age , tidak berubah. Lagipun, smudge ialah pembolehubah rujukan yang masih menunjuk kepada objek asal yang lama dengan umur 5 tahun, dan kami tidak melakukan apa-apa dengan objek itu. Semua perubahan umur kami dilakukan pada objek baharu. Jadi, ternyata objek dihantar ke kaedah melalui rujukan. Salinan objek tidak pernah dibuat secara automatik. Jika anda menghantar objek kucing kepada kaedah dan menukar umurnya, anda akan menukar umurnya. Tetapi pembolehubah rujukan disalin apabila memberikan nilai dan/atau kaedah panggilan! Mari ulangi di sini apa yang kami katakan tentang lulus primitif: "Apabila kami memanggil kaedah changeInt() dan lulus intpembolehubah x (=15) , kaedah itu tidak mendapat pembolehubah x itu sendiri, sebaliknya salinannya. Oleh itu, sebarang perubahan yang dibuat pada salinan tidak menjejaskan x asal kamiSaya masih akan berdebat lebih daripada sekali tentang cara hujah diluluskan di Jawa (walaupun di kalangan pembangun berpengalaman). Tetapi, kini anda tahu dengan tepat cara ia berfungsi. Teruskan! :) Untuk mengukuhkan perkara yang anda pelajari, kami cadangkan anda menonton pelajaran video daripada Kursus Java kami
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION