Sök…


Introduktion

Objekt har tillstånd och beteenden. Exempel: En hund har tillstånd - färg, namn, ras samt beteenden - vaggar med svansen, skäller, äter. Ett objekt är ett exempel på en klass.

Klass - En klass kan definieras som en mall / plan som beskriver det beteende / tillstånd som objektet för dess typ stöder.

Syntax

  • klass Exempel {} // klass sökord, namn, kropp

Enklaste möjliga klass

class TrivialClass {}

En klass består vid ett minimum av class nyckelordet, ett namn, och en kropp, som kan vara tom.

Du startar en klass med den new operatören.

TrivialClass tc = new TrivialClass();

Objektmedlem vs statisk medlem

Med den här klassen:

class ObjectMemberVsStaticMember {

    static int staticCounter = 0;
    int memberCounter = 0;

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

följande kodavsnitt:

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);

producerar denna utgång:

o1 static counter 3
o1 member counter 1

o2 static counter 3
o2 member counter 2

ObjectMemberVsStaticMember.staticCounter = 3

Obs: Du bör inte ringa static medlemmar på objekt utan på klasser. Även om det inte gör någon skillnad för JVM kommer mänskliga läsare att uppskatta det.

static medlemmar ingår i klassen och finns bara en gång per klass. Icke- static medlemmar finns i fall, det finns en oberoende kopia för varje instans. Detta innebär också att du behöver tillgång till ett objekt i den klassen för att få åtkomst till dess medlemmar.

Metoder för överbelastning

Ibland måste samma funktionalitet skrivas för olika typer av ingångar. Vid den tiden kan man använda samma metodnamn med en annan uppsättning parametrar. Varje olika uppsättning parametrar är känd som en metodsignatur. Som framgår av exemplet kan en enda metod ha flera signaturer.

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"
    }
}

Fördelen är att samma funktionalitet kallas med två olika antal ingångar. När man anropar metoden enligt den ingång vi passerar (i detta fall antingen ett strängvärde eller två strängvärden) körs motsvarande metod.

Metoder kan överbelastas:

  1. Baserat på antalet passerade parametrar .

    Exempel: method(String s) och method(String s1, String s2) .

  1. Baserat på parametrarnas ordning .

    Exempel: method(int i, float f) och method(float f, int i)) .

Obs! Metoder kan inte överbelastas genom att bara ändra returtypen ( int method() anses vara samma som String method() och kommer att kasta en RuntimeException om du försöker). Om du ändrar returtyp måste du också ändra parametrarna för att överbelasta.

Grundläggande konstruktion och användning av objekt

Objekt kommer i sin egen klass, så ett enkelt exempel skulle vara en bil (detaljerade förklaringar nedan):

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;
    }
    
}  

Objekt är exempel på deras klass. Så, hur du skapar ett objekt skulle vara genom att ringa bilklassen på ett av två sätt i din huvudklass (huvudmetod i Java eller onCreate i Android).

Alternativ 1

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

Alternativ 1 är där du i princip berättar programmet allt om bilen när objektet skapades. Ändring av bilens egendom skulle kräva att man ringer till en av metoderna som repaintCar metoden. Exempel:

 newCar.repaintCar("Blue");

Obs: Se till att du överför rätt datatyp till metoden. I exemplet ovan kan du också skicka en variabel till metoden repaintCar så länge datatypen är korrekt .

Det var ett exempel på att ändra egenskaper hos ett objekt, att ta emot egenskaper för ett objekt skulle kräva att man använder en metod från Car-klassen som har ett returvärde (vilket betyder en metod som inte är void ). Exempel:

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

Alternativ 1 är det bästa alternativet när du har alla objektets data vid skapandet.

Alternativ 2

`Car newCar = new Car();

Alternativ 2 får samma effekt men krävs mer arbete för att skapa ett objekt korrekt. Jag vill komma ihåg denna konstruktör i bilklassen:

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

Lägg märke till att du inte faktiskt behöver skicka några parametrar till objektet för att skapa det. Detta är mycket användbart för när du inte har alla aspekter av objektet men du måste använda de delar du har. Detta sätter generiska data i var och en av instansvariablerna i objektet så att, om du efterlyser en data som inte finns, inga fel kastas.

Obs: Glöm inte att du måste ställa in delar av objektet senare som du inte initierade det med. Till exempel,

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

Detta är ett vanligt misstag bland objekt som inte initialiseras med alla deras data. Fel undviks eftersom det finns en konstruktör som gör att ett tomt bilobjekt kan skapas med stand-in-variabler ( public Car(){} ), men ingen del av myCar anpassades faktiskt. Rätt exempel på att skapa bilobjekt:

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

Och som en påminnelse, få ett objekts egenskaper genom att anropa en metod i din huvudklass. Exempel:

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

konstruktörer

Konstruktörer är speciella metoder uppkallad efter klassen och utan returtyp och används för att konstruera föremål. Konstruktörer, som metoder, kan ta inputparametrar. Konstruktörer används för att initialisera objekt. Abstrakta klasser kan också ha konstruktörer.

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

Det är viktigt att förstå att konstruktörer skiljer sig från metoder på flera sätt:

  1. Konstruktörer kan endast ta modifierarna public , private och protected och kan inte förklaras abstract , final , static eller synchronized .

  2. Konstruktörer har ingen returtyp.

  3. Konstruktörer MÅSTE namnges samma som klassnamnet. I Hello exemplet är Hello objekts konstruktörsnamn detsamma som klassnamnet.

  4. Det this nyckelordet har en extra användning i konstruktörer. this.method(...) kallar en metod i den aktuella instansen, medan this(...) hänvisar till en annan konstruktör i den aktuella klassen med olika signaturer.

Konstruktörer kan också kallas genom arv med hjälp av nyckelordet super .

public class SuperManClass{

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


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

Se Java Language Specification # 8.8 och # 15.9

Initiera statiska slutfält med en statisk initialisering

För att initialisera ett static final slutfält som kräver användning av mer än ett enda uttryck kan en static initialisering användas för att tilldela värdet. Följande exempel initialiserar en omodifierbar uppsättning String :

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);
    }
}

Förklara vad som är metodöverbelastning och åsidosättande.

Metodöverskridande och överbelastning är två former av polymorfism som stöds av Java.

Metod överbelastning

Metodöverbelastning (även känd som statisk polymorfism) är ett sätt du kan ha två (eller fler) metoder (funktioner) med samma namn i en enda klass. Ja, det är så enkelt som det.

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;
    }
}

På detta sätt kan användaren ringa samma metod för område beroende på vilken form den har.

Men den verkliga frågan är nu, hur kommer java-kompilatoren att skilja på vilken metodkropp som ska köras?

Nåväl Java har gjort det klart att även om metodnamnen ( area() i vårt fall) kan vara samma men argumentmetoden tar bör vara annorlunda.

Överbelastade metoder måste ha olika argumentlista (kvantitet och typer).

Med det sagt kan vi inte lägga till en annan metod för att beräkna area på en kvadrat som denna: public Double area(Long side) eftersom det i detta fall kommer i konflikt med områdesmetod för cirkel och orsakar oklarhet för java-kompilatorn.

Tack och lov, det finns vissa avslappningar när du skriver överbelastade metoder som

Kan ha olika returtyper.

Kan ha olika åtkomstmodifierare.

Kan kasta olika undantag.

Varför kallas detta statisk polymorfism?

Tja, det beror på vilka överbelastade metoder som ska åberopas och beslutas vid sammanställningstiden, baserat på det faktiska antalet argument och argumentets sammanställningstidstyper.

En av de vanligaste orsakerna till att använda metodöverbelastning är enkelhetens kod den tillhandahåller. String.valueOf() ihåg till exempel String.valueOf() som tar nästan alla typer av argument? Det som skrivs bakom scenen är förmodligen något liknande:

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) 

Metodöverskridande

Tja, åsidosättande av metod (ja du antar att det är rätt, det kallas också dynamisk polymorfism) är något mer intressant och komplicerat ämne.

Vid metodöverskridande skriv vi över metodkroppen som tillhandahålls av förälderklassen. Jag fattar? Nej? Låt oss gå igenom ett exempel.

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

Så vi har en klass som heter Shape och den har metod som heter area som förmodligen kommer att returnera formens område.

Låt oss säga att vi nu har två klasser som heter Circle and 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;
    }
}

Likaså rektangelklass:

 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;
    }
}

Så nu båda dina barn klasser har uppdaterat metod kropp från den överordnade ( Shape ) klass. Nu är frågan hur man ser resultatet? Låt psvm göra det på det gamla psvm sättet.

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());            
        
    }
}

Wow! är det inte bra? Två objekt av samma typ som kallar samma metoder och returnerar olika värden. Min vän, det är kraften i dynamisk polymorfism.

Här är ett diagram för att bättre jämföra skillnaderna mellan dessa två: -

Metod överbelastning Metodöverskridande
Metodöverbelastning används för att öka programmets läsbarhet. Metodöverskridande används för att tillhandahålla den specifika implementeringen av metoden som redan tillhandahålls av dess superklass.
Metodöverbelastning utförs inom klassen. Överskridande av metod sker i två klasser som har IS-A (arv).
Vid överbelastning av metoden måste parametern vara annorlunda. Om metoden åsidosätts måste parametern vara densamma.
Metodöverbelastning är exemplet på kompilering av tidspolymorfism. Överskridande av metoden är exemplet på polymorfism av körtid.
I java kan metodöverbelastning inte utföras genom att endast ändra metodens returtyp. Returtyp kan vara samma eller annorlunda i metodöverbelastning. Men du måste behöva ändra parametern. Returtyp måste vara densamma eller överensstämmande vid metodöverskridande.


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow