Suche…


Einführung

Objekte haben Zustände und Verhalten. Beispiel: Ein Hund hat Zustände - Farbe, Name, Rasse sowie Verhalten - Schwanzwedeln, Bellen, Fressen. Ein Objekt ist eine Instanz einer Klasse.

Klasse - Eine Klasse kann als Vorlage / Plan definiert werden, die das Verhalten / den Zustand beschreibt, den das Objekt seines Typs unterstützt.

Syntax

  • class Beispiel {} // Klassenschlüssel, Name, Hauptteil

Einfachste mögliche Klasse

class TrivialClass {}

Eine Klasse besteht mindestens aus dem Schlüsselwort class , einem Namen und einem Körper, der leer sein kann.

Sie instanziieren eine Klasse mit dem new Operator.

TrivialClass tc = new TrivialClass();

Objektmitglied vs statisches Mitglied

Mit dieser Klasse:

class ObjectMemberVsStaticMember {

    static int staticCounter = 0;
    int memberCounter = 0;

    void increment() {
        staticCounter ++;
        memberCounter++;
    }
}

das folgende Code-Snippet:

final ObjectMemberVsStaticMember o1 = new ObjectMemberVsStaticMember();
final ObjectMemberVsStaticMember o2 = new ObjectMemberVsStaticMember();

o1.increment();

o2.increment();
o2.increment();

System.out.println("o1 static counter " + o1.staticCounter);
System.out.println("o1 member counter " + o1.memberCounter);
System.out.println();

System.out.println("o2 static counter " + o2.staticCounter);
System.out.println("o2 member counter " + o2.memberCounter);
System.out.println();

System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.staticCounter);

// the following line does not compile. You need an object
// to access its members
//System.out.println("ObjectMemberVsStaticMember.staticCounter = " + ObjectMemberVsStaticMember.memberCounter);

produziert diese Ausgabe:

o1 static counter 3
o1 member counter 1

o2 static counter 3
o2 member counter 2

ObjectMemberVsStaticMember.staticCounter = 3

Anmerkung: Sie sollten static Member nicht für Objekte, sondern für Klassen aufrufen. Während es für die JVM keinen Unterschied macht, werden menschliche Leser das zu schätzen wissen.

static Member sind Teil der Klasse und existieren nur einmal pro Klasse. Für Instanzen gibt es nicht static Member. Für jede Instanz gibt es eine unabhängige Kopie. Dies bedeutet auch, dass Sie Zugriff auf ein Objekt dieser Klasse benötigen, um auf seine Mitglieder zugreifen zu können.

Überladungsmethoden

Manchmal muss die gleiche Funktionalität für verschiedene Arten von Eingaben geschrieben werden. Zu diesem Zeitpunkt kann derselbe Methodenname mit einem anderen Parametersatz verwendet werden. Jeder unterschiedliche Parametersatz wird als Methodensignatur bezeichnet. Wie aus dem Beispiel hervorgeht, kann eine einzelne Methode mehrere Signaturen haben.

public class Displayer {

    public void displayName(String firstName) {
        System.out.println("Name is: " + firstName);
    }

    public void displayName(String firstName, String lastName) {
        System.out.println("Name is: " + firstName + " " + lastName);
    }

    public static void main(String[] args) {
        Displayer displayer = new Displayer();
        displayer.displayName("Ram");          //prints "Name is: Ram"
        displayer.displayName("Jon", "Skeet"); //prints "Name is: Jon Skeet"
    }
}

Der Vorteil ist, dass die gleiche Funktionalität mit zwei unterschiedlichen Eingangszahlen aufgerufen wird. Beim Aufrufen der Methode gemäß der übergebenen Eingabe (in diesem Fall entweder ein Stringwert oder zwei Stringwerte) wird die entsprechende Methode ausgeführt.

Methoden können überlastet sein:

  1. Basierend auf der Anzahl der übergebenen Parameter .

    Beispiel: method(String s) und method(String s1, String s2) .

  1. Basierend auf der Reihenfolge der Parameter .

    Beispiel: method(int i, float f) und method(float f, int i)) .

Hinweis: Methoden können nicht durch eine Änderung nur den Rückgabetyp (überlastet werden int method() - String method() RuntimeException int method() gilt das gleiche wie String method() - String method() und einen werfen RuntimeException wenn versucht wird ). Wenn Sie den Rückgabetyp ändern, müssen Sie auch die Parameter ändern, um überladen zu werden.

Grundlegende Objektkonstruktion und Verwendung

Objekte kommen in eine eigene Klasse, ein einfaches Beispiel wäre ein Auto (detaillierte Erklärungen unten):

public class Car {
    
    //Variables describing the characteristics of an individual car, varies per  object
   private int milesPerGallon;
   private String name;
   private String color;
   public int numGallonsInTank; 
    
    public Car(){
        milesPerGallon = 0;
        name = "";
        color = "";
        numGallonsInTank = 0;
    }
    
    //this is where an individual object is created
    public Car(int mpg, int, gallonsInTank, String carName, String carColor){
        milesPerGallon = mpg;
        name = carName;
        color = carColor;
        numGallonsInTank = gallonsInTank;
    }

    //methods to make the object more usable

    //Cars need to drive
    public void drive(int distanceInMiles){
        //get miles left in car
        int miles = numGallonsInTank * milesPerGallon;
        
        //check that car has enough gas to drive distanceInMiles
        if (miles <= distanceInMiles){
            numGallonsInTank = numGallonsInTank - (distanceInMiles / milesPerGallon)
            System.out.println("Drove " + numGallonsInTank + " miles!");
        } else {
            System.out.println("Could not drive!");
        }
    }

    public void paintCar(String newColor){
        color = newColor;
    }
        //set new Miles Per Gallon
    public void setMPG(int newMPG){
        milesPerGallon = newMPG;
    }

       //set new number of Gallon In Tank
    public void setGallonsInTank(int numGallons){
        numGallonsInTank = numGallons;
    }
    
    public void nameCar(String newName){
        name = newName;
    }

    //Get the Car color
    public String getColor(){
        return color;
    }

    //Get the Car name
    public String getName(){
        return name;
    }

    //Get the number of Gallons
    public String getGallons(){
        return numGallonsInTank;
    }
    
}  

Objekte sind Instanzen ihrer Klasse. Die Art und Weise, wie Sie ein Objekt erstellen würden , wäre, die Car-Klasse auf zwei Arten in Ihrer Hauptklasse aufzurufen (Hauptmethode in Java oder onCreate in Android).

Option 1

`Car newCar = new Car(30, 10, "Ferrari", "Red");

Bei Option 1 teilen Sie dem Programm beim Erstellen des Objekts im Wesentlichen alles über das Auto mit. Wenn Sie eine Eigenschaft des Autos repaintCar , müssen Sie eine der Methoden aufrufen, z. B. die Methode repaintCar . Beispiel:

 newCar.repaintCar("Blue");

Anmerkung: Stellen Sie sicher, dass Sie den korrekten Datentyp an die Methode übergeben. Im obigen Beispiel können Sie auch eine Variable an die Methode repaintCar , solange der Datentyp korrekt ist .

Dies war ein Beispiel für das Ändern der Eigenschaften eines Objekts. Für das Empfangen von Eigenschaften eines Objekts müsste eine Methode aus der Klasse Car verwendet werden, die einen Rückgabewert enthält (dh eine Methode, die nicht void ). Beispiel:

String myCarName = newCar.getName();  //returns string "Ferrari"

Option 1 ist die beste Option, wenn Sie zum Zeitpunkt der Erstellung über alle Daten des Objekts verfügen.

Option 2

`Car newCar = new Car();

Option 2 erzielt den gleichen Effekt, erfordert jedoch mehr Arbeit, um ein Objekt korrekt zu erstellen. Ich möchte mich an diesen Konstruktor in der Autoklasse erinnern:

public void Car(){
        milesPerGallon = 0;
        name = "";
        color = "";
        numGallonsInTank = 0;
    }

Beachten Sie, dass Sie keine Parameter tatsächlich an das Objekt übergeben müssen, um es zu erstellen. Dies ist sehr nützlich, wenn Sie nicht alle Aspekte des Objekts haben, aber die Teile verwenden müssen, die Sie haben. Dadurch werden generische Daten in jede der Instanzvariablen des Objekts festgelegt, sodass, wenn Sie Daten anfordern, die nicht vorhanden sind, keine Fehler ausgegeben werden.

Hinweis: Vergessen Sie nicht, dass Sie später die Teile des Objekts festlegen müssen, mit denen Sie es nicht initialisiert haben. Zum Beispiel,

Car myCar = new Car();
String color = Car.getColor(); //returns empty string

Dies ist ein häufiger Fehler bei Objekten, die nicht mit all ihren Daten initialisiert werden. Fehler wurden vermieden, da es einen Konstruktor gibt, der die Erstellung eines leeren Car-Objekts mit Stand-In-Variablen ermöglicht ( public Car(){} ), aber kein Teil des myCar wurde tatsächlich angepasst. Korrektes Beispiel für das Erstellen eines Car-Objekts:

Car myCar = new Car();
myCar.nameCar("Ferrari");
myCar.paintCar("Purple");
myCar.setGallonsInTank(10);
myCar.setMPG(30);

Rufen Sie als Erinnerung die Eigenschaften eines Objekts ab, indem Sie eine Methode in Ihrer Hauptklasse aufrufen. Beispiel:

String myCarName = myCar.getName(); //returns string "Ferrari"

Konstrukteure

Konstruktoren sind spezielle Methoden, die nach der Klasse und ohne Rückgabetyp benannt werden, und werden zum Erstellen von Objekten verwendet. Konstruktoren können wie Methoden Eingabeparameter annehmen. Konstruktoren werden zum Initialisieren von Objekten verwendet. Abstrakte Klassen können auch Konstruktoren haben.

public class Hello{
    // constructor
    public Hello(String wordToPrint){
        printHello(wordToPrint);
    }
    public void printHello(String word){
        System.out.println(word);
    }
}
// instantiates the object during creating and prints out the content
// of wordToPrint

Es ist wichtig zu verstehen, dass Konstruktoren sich in mehrfacher Hinsicht von Methoden unterscheiden:

  1. Konstruktoren können nur die Modifizierer public , private und protected und können nicht als abstract , final , static oder synchronized deklariert werden.

  2. Konstruktoren haben keinen Rückgabetyp.

  3. Konstruktoren MÜSSEN genauso benannt werden wie der Klassenname. Im Hello Beispiel Hello der Konstruktorname des Hello Objekts mit dem Klassennamen überein.

  4. Das Schlüsselwort this hat eine zusätzliche Verwendung in Konstruktoren. this.method(...) ruft eine Methode in der aktuellen Instanz auf, während this(...) auf einen anderen Konstruktor in der aktuellen Klasse mit unterschiedlichen Signaturen verweist.

Konstruktoren können auch durch Vererbung mit dem Schlüsselwort super aufgerufen werden.

public class SuperManClass{

    public SuperManClass(){
        // some implementation
    }
    
    // ... methods
}


public class BatmanClass extends SupermanClass{
    public BatmanClass(){
        super();
    }
    //... methods...
}

Siehe Java-Sprachspezifikation Nr. 8.8 und Nr. 15.9

Statische Endfelder werden mit einem statischen Initialisierer initialisiert

Um ein static final Endfeld zu initialisieren, für das mehr als ein einzelner Ausdruck erforderlich ist, kann der Wert mit einem static Initialisierer zugewiesen werden. Das folgende Beispiel initialisiert eine nicht veränderbare Menge von String s:

public class MyClass {

    public static final Set<String> WORDS;
    
    static {
        Set<String> set = new HashSet<>();
        set.add("Hello");
        set.add("World");
        set.add("foo");
        set.add("bar");
        set.add("42");
        WORDS = Collections.unmodifiableSet(set);
    }
}

Erklären, was Methodenüberladen und Überschreiben ist.

Überschreiben und Überladen von Methoden sind zwei von Java unterstützte Formen von Polymorphismus.

Methodenüberladung

Überladen von Methoden (auch als statischer Polymorphismus bezeichnet) ist eine Möglichkeit, zwei (oder mehr) Methoden (Funktionen) mit demselben Namen in einer einzigen Klasse zu haben. Ja, so einfach ist das.

public class Shape{
    //It could be a circle or rectangle or square
    private String type;
    
    //To calculate area of rectangle
    public Double area(Long length, Long breadth){
        return (Double) length * breadth;
    }
    
     //To calculate area of a circle
     public Double area(Long radius){
        return (Double) 3.14 * r * r;
    }
}

Auf diese Weise kann der Benutzer dieselbe Methode für den Bereich aufrufen, abhängig von der Art der Form, die er hat.

Aber die eigentliche Frage ist nun, wie der Java-Compiler unterscheidet, welcher Methodenkörper ausgeführt werden soll.

Nun, Java hat deutlich gemacht, dass die Methodennamen ( area() in unserem Fall) zwar gleich sein können, die Argumente jedoch anders sind.

Überladene Methoden müssen eine unterschiedliche Argumentliste haben (Anzahl und Typen).

Allerdings können wir keine andere Methode hinzufügen, um die Fläche eines Quadrats wie folgt zu berechnen: public Double area(Long side) da in diesem Fall die Flächenmethode des Kreises in Konflikt gerät und Mehrdeutigkeiten für den Java-Compiler auftreten.

Gott sei Dank, gibt es einige Entspannungen beim Schreiben überladener Methoden wie

Kann unterschiedliche Rückgabetypen haben.

Kann unterschiedliche Zugriffsmodifizierer haben.

Kann verschiedene Ausnahmen werfen.

Warum heißt das statischer Polymorphismus?

Das liegt daran, dass die überladene Methode zur Kompilierzeit festgelegt wird, basierend auf der tatsächlichen Anzahl der Argumente und den Kompilierzeittypen der Argumente.

Einer der häufigsten Gründe für das Überladen von Methoden ist die Einfachheit des bereitgestellten Codes. Erinnern Sie sich beispielsweise an String.valueOf() das fast alle Arten von Argumenten String.valueOf() ? Was hinter der Szene steht, ist wahrscheinlich so:

static String valueOf(boolean b) 
static String valueOf(char c) 
static String valueOf(char[] data) 
static String valueOf(char[] data, int offset, int count) 
static String valueOf(double d) 
static String valueOf(float f) 
static String valueOf(int i) 
static String valueOf(long l) 
static String valueOf(Object obj) 

Überschreiben der Methode

Nun, das Überschreiben von Methoden (Ja, Sie denken, es wird auch als dynamischer Polymorphismus bezeichnet) ist ein etwas interessanteres und komplexeres Thema.

Beim Überschreiben der Methode überschreiben wir den von der übergeordneten Klasse bereitgestellten Methodenkörper. Ich habs? Nein? Gehen wir ein Beispiel durch.

public abstract class Shape{
    
    public abstract Double area(){
        return 0.0;
    }
}

Wir haben also eine Klasse namens Shape und eine Methode namens area, die wahrscheinlich den Bereich der Form zurückgibt.

Nehmen wir an, wir haben jetzt zwei Klassen mit dem Namen Circle und Rectangle.

public class Circle extends Shape {
    private Double radius = 5.0;

    // See this annotation @Override, it is telling that this method is from parent
    // class Shape and is overridden here
    @Override
    public Double area(){
        return 3.14 * radius * radius;
    }
}

Ähnlich Rechteckklasse:

 public class Rectangle extends Shape {
    private Double length = 5.0;
    private Double breadth= 10.0;


    // See this annotation @Override, it is telling that this method is from parent
    // class Shape and is overridden here
    @Override
    public Double area(){
        return length * breadth;
    }
}

Jetzt haben beide Kind-Klassen den von der Eltern-Klasse ( Shape ) bereitgestellten Methodenkörper aktualisiert. Nun ist die Frage, wie das Ergebnis zu sehen ist. Nun, machen wir es auf die alte psvm Weise.

public class AreaFinder{
    
    public static void main(String[] args){

        //This will create an object of circle class
        Shape circle = new Circle();
        //This will create an object of Rectangle class
        Shape rectangle = new Rectangle();
        
        // Drumbeats ......
        //This should print 78.5
        System.out.println("Shape of circle : "+circle.area());

        //This should print 50.0
        System.out.println("Shape of rectangle: "+rectangle.area());            
        
    }
}

Beeindruckend! ist es nicht toll? Zwei Objekte desselben Typs, die dieselben Methoden aufrufen und unterschiedliche Werte zurückgeben. Mein Freund, das ist die Kraft des dynamischen Polymorphismus.

Hier ist ein Diagramm zum besseren Vergleich der Unterschiede zwischen diesen beiden: -

Methodenüberladung Überschreiben der Methode
Methodenüberladung wird verwendet, um die Lesbarkeit des Programms zu erhöhen. Das Überschreiben von Methoden wird verwendet, um die spezifische Implementierung der Methode bereitzustellen, die bereits von ihrer Oberklasse bereitgestellt wird.
Das Überladen der Methode wird innerhalb der Klasse durchgeführt. Das Überschreiben von Methoden tritt in zwei Klassen auf, die eine IS-A-Beziehung (Vererbung) haben.
Bei Überladung der Methode müssen die Parameter unterschiedlich sein. Im Falle eines Überschreibens der Methode muss der Parameter derselbe sein.
Methodenüberladung ist das Beispiel für die Kompilierzeit-Polymorphie. Das Überschreiben von Methoden ist das Beispiel für Laufzeitpolymorphismus.
In Java kann das Überladen von Methoden nicht durchgeführt werden, indem nur der Rückgabetyp der Methode geändert wird. Der Rückgabetyp kann in der Methodenüberladung gleich oder verschieden sein. Sie müssen jedoch den Parameter ändern. Der Rückgabetyp muss beim Überschreiben der Methode gleich oder kovariant sein.


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow