Java Language
Classi e oggetti
Ricerca…
introduzione
Gli oggetti hanno stati e comportamenti. Esempio: un cane ha degli stati - colore, nome, razza e comportamenti - scodinzolando, abbaiando, mangiando. Un oggetto è un'istanza di una classe.
Classe - Una classe può essere definita come un modello / modello che descrive il comportamento / stato che l'oggetto del suo tipo supporta.
Sintassi
- Esempio di classe {} // class parola chiave, nome, corpo
La più semplice possibile
class TrivialClass {}
Una classe comprende almeno la parola chiave class
, un nome e un corpo, che potrebbe essere vuoto.
Si istanzia una classe con il new
operatore.
TrivialClass tc = new TrivialClass();
Membro oggetto vs membro statico
Con questa classe:
class ObjectMemberVsStaticMember {
static int staticCounter = 0;
int memberCounter = 0;
void increment() {
staticCounter ++;
memberCounter++;
}
}
il seguente frammento di codice:
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);
produce questo risultato:
o1 static counter 3
o1 member counter 1
o2 static counter 3
o2 member counter 2
ObjectMemberVsStaticMember.staticCounter = 3
Nota: non chiamare static
membri static
sugli oggetti, ma sulle classi. Mentre non fa la differenza per la JVM, i lettori umani lo apprezzeranno.
static
membri static
fanno parte della classe ed esistono solo una volta per classe. I membri non static
esistono sulle istanze, esiste una copia indipendente per ogni istanza. Ciò significa anche che è necessario accedere a un oggetto di quella classe per accedere ai suoi membri.
Metodi di sovraccarico
A volte è necessario scrivere la stessa funzionalità per diversi tipi di input. A quel tempo, si può usare lo stesso nome di metodo con un diverso set di parametri. Ogni diverso insieme di parametri è noto come firma del metodo. Come visto nell'esempio, un singolo metodo può avere più firme.
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"
}
}
Il vantaggio è che la stessa funzionalità viene chiamata con due diversi numeri di input. Durante il richiamo del metodo in base all'input che stiamo passando, (in questo caso un valore di stringa o due valori di stringa) viene eseguito il metodo corrispondente.
I metodi possono essere sovraccaricati:
In base al numero di parametri passati.
Esempio:
method(String s)
emethod(String s1, String s2)
.
Basato sull'ordine dei parametri .
Esempio:
method(int i, float f)
emethod(float f, int i))
.
Nota: i metodi non possono essere sovraccaricati modificando solo il tipo restituito (il int method()
è considerato uguale al String method()
e genera una RuntimeException
se tentata). Se si modifica il tipo di reso, è necessario modificare anche i parametri per sovraccaricare.
Costruzione e uso di oggetti di base
Gli oggetti arrivano nella loro classe, quindi un semplice esempio potrebbe essere una macchina (spiegazioni dettagliate di seguito):
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;
}
}
Gli oggetti sono esempi della loro classe. Quindi, il modo in cui creeresti un oggetto sarebbe chiamando la classe Car in due modi nella tua classe principale (metodo principale in Java o onCreate in Android).
opzione 1
`Car newCar = new Car(30, 10, "Ferrari", "Red");
L'opzione 1 è quella in cui essenzialmente dici al programma tutto ciò che riguarda l'auto alla creazione dell'oggetto. La modifica di qualsiasi proprietà della macchina richiederebbe di chiamare uno dei metodi come il metodo repaintCar
. Esempio:
newCar.repaintCar("Blue");
Nota: assicurati di passare il tipo di dati corretto al metodo. Nell'esempio precedente, è anche possibile passare una variabile al metodo repaintCar
a condizione che il tipo di dati sia corretto .
Quello era un esempio di modifica delle proprietà di un oggetto, la ricezione di proprietà di un oggetto richiederebbe l'utilizzo di un metodo dalla classe Car che ha un valore di ritorno (ovvero un metodo che non è void
). Esempio:
String myCarName = newCar.getName(); //returns string "Ferrari"
L'opzione 1 è l'opzione migliore quando si hanno tutti i dati dell'oggetto al momento della creazione.
opzione 2
`Car newCar = new Car();
L'opzione 2 ottiene lo stesso effetto ma richiede più lavoro per creare correttamente un oggetto. Voglio ricordare questo Costruttore nella classe Car:
public void Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}
Si noti che non è necessario passare effettivamente alcun parametro nell'oggetto per crearlo. Questo è molto utile quando non si hanno tutti gli aspetti dell'oggetto, ma è necessario utilizzare le parti che si hanno. Questo imposta i dati generici in ciascuna delle variabili di istanza dell'oggetto in modo che, se si richiama un dato che non esiste, non vengono generati errori.
Nota: non dimenticare che è necessario impostare le parti dell'oggetto in un secondo momento per il quale non è stato inizializzato. Per esempio,
Car myCar = new Car();
String color = Car.getColor(); //returns empty string
Questo è un errore comune tra gli oggetti che non sono inizializzati con tutti i loro dati. Gli errori sono stati evitati perché c'è un Costruttore che consente di creare un oggetto Car vuoto con variabili stand-in ( public Car(){}
), ma nessuna parte della myCar è stata effettivamente personalizzata. Esempio corretto di creazione di oggetto auto:
Car myCar = new Car();
myCar.nameCar("Ferrari");
myCar.paintCar("Purple");
myCar.setGallonsInTank(10);
myCar.setMPG(30);
E, come promemoria, ottieni le proprietà di un oggetto chiamando un metodo nella tua classe principale. Esempio:
String myCarName = myCar.getName(); //returns string "Ferrari"
Costruttori
I costruttori sono metodi speciali che prendono il nome dalla classe e senza un tipo di ritorno e sono usati per costruire oggetti. I costruttori, come i metodi, possono prendere i parametri di input. I costruttori sono utilizzati per inizializzare gli oggetti. Le classi astratte possono avere anche costruttori.
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
È importante capire che i costruttori sono diversi dai metodi in diversi modi:
I costruttori possono solo rendere i modificatori
public
,private
eprotected
e non possono essere dichiaratiabstract
,final
,static
osynchronized
.I costruttori non hanno un tipo di ritorno.
I costruttori DEVONO essere nominati come il nome della classe. Nell'esempio
Hello
, il nome del costruttore dell'oggettoHello
è uguale al nome della classe.this
parola chiave ha un utilizzo aggiuntivo all'interno dei costruttori.this.method(...)
chiama un metodothis.method(...)
corrente, mentrethis(...)
riferisce a un altro costruttore nella classe corrente con diverse firme.
I costruttori possono anche essere richiamati attraverso l'ereditarietà usando la parola chiave super
.
public class SuperManClass{
public SuperManClass(){
// some implementation
}
// ... methods
}
public class BatmanClass extends SupermanClass{
public BatmanClass(){
super();
}
//... methods...
}
Vedere le specifiche della lingua Java # 8.8 e # 15.9
Inizializzazione di campi finali statici mediante un inizializzatore statico
Per inizializzare static final
campi static final
che richiedono l'utilizzo di più di una singola espressione, è possibile utilizzare un inizializzatore static
per assegnare il valore. L'esempio seguente inizializza un insieme non modificabile di 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);
}
}
Spiegare qual è il metodo di sovraccarico e di sovrascrittura.
Il metodo Overriding e Overloading sono due forme di polimorfismo supportate da Java.
Sovraccarico del metodo
L'overloading del metodo (noto anche come Polymorphism statico) è un modo in cui è possibile avere due (o più) metodi (funzioni) con lo stesso nome in una singola classe. Sì, è così semplice.
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;
}
}
In questo modo l'utente può chiamare lo stesso metodo per l'area a seconda del tipo di forma che ha.
Ma la vera domanda ora è, in che modo il compilatore java distinguerà quale metodo deve essere eseguito?
Bene, Java ha chiarito che anche se i nomi dei metodi ( area()
nel nostro caso) possono essere uguali, ma il metodo degli argomenti sta prendendo dovrebbe essere diverso.
I metodi sovraccaricati devono avere elenchi di argomenti diversi (quantità e tipi).
Detto questo non possiamo aggiungere un altro metodo per calcolare l'area di un quadrato come questo: public Double area(Long side)
perché in questo caso, entrerà in conflitto con il metodo area del cerchio e causerà ambiguità per il compilatore java.
Grazie a dio, ci sono alcuni rilassamenti durante la scrittura di metodi sovraccarichi come
Può avere diversi tipi di rendimento.
Può avere diversi modificatori di accesso.
Può lanciare diverse eccezioni.
Perché questo è chiamato polimorfismo statico?
Beh, questo è il motivo per cui i metodi di overload che devono essere invocati vengono decisi al momento della compilazione, in base al numero effettivo di argomenti e ai tipi di argomenti in fase di compilazione.
Uno dei motivi comuni dell'utilizzo dell'overload dei metodi è la semplicità del codice fornito. Ad esempio, ricorda
String.valueOf()
che accetta quasi ogni tipo di argomento? Quello che è scritto dietro la scena è probabilmente qualcosa del genere: -
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)
Metodo Overriding
Bene, il metodo che sovrascrive (sì, lo indovini, è anche conosciuto come polimorfismo dinamico) è un argomento un po 'più interessante e complesso.
Nel metodo che sovrascrive, sovrascriviamo il corpo del metodo fornito dalla classe genitore. Fatto? No? Facciamo un esempio.
public abstract class Shape{
public abstract Double area(){
return 0.0;
}
}
Quindi abbiamo una classe chiamata Shape e ha un metodo chiamato area che probabilmente restituirà l'area della forma.
Diciamo che ora abbiamo due classi chiamate Circle e 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;
}
}
Allo stesso modo, classe rettangolo:
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;
}
}
Quindi, ora entrambe le classi dei bambini hanno un corpo del metodo aggiornato fornito dalla classe padre ( Shape
). Ora la domanda è come vedere il risultato? Bene, lascia fare al vecchio modo di psvm
.
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! non è fantastico? Due oggetti dello stesso tipo chiamano gli stessi metodi e restituiscono valori diversi. Amico mio, questo è il potere del polimorfismo dinamico.
Ecco una tabella per confrontare meglio le differenze tra questi due: -
Sovraccarico del metodo | Metodo Overriding |
---|---|
Il sovraccarico del metodo viene utilizzato per aumentare la leggibilità del programma. | L'override del metodo viene utilizzato per fornire l'implementazione specifica del metodo che è già fornito dalla sua super classe. |
L'overloading del metodo viene eseguito all'interno della classe. | L'override del metodo si verifica in due classi che hanno una relazione IS-A (ereditarietà). |
In caso di sovraccarico del metodo, il parametro deve essere diverso. | In caso di override del metodo, i parametri devono essere uguali. |
L'overloading del metodo è l'esempio del polimorfismo del tempo di compilazione. | L'override del metodo è l'esempio del polimorfismo del tempo di esecuzione. |
In Java, l'overloading dei metodi non può essere eseguito cambiando solo il tipo di ritorno del metodo. Il tipo di reso può essere uguale o diverso nell'overload del metodo. Ma è necessario modificare il parametro. | Il tipo di restituzione deve essere uguale o covariante nel metodo prioritario. |