Continuăm seria de articole Java cu clasele Inner. Acestea sunt puțin folosite față de reprezentarea lambda a acestora. Avantajul principal constă în separarea contextelor și în accesul claselor Inner la variabilele private din clasa de bază.
public class Outside {
private int count;
public Outside(int nr){
this.count=nr;
}
class Inner {
public void showCount(){
System.out.println(“count is:”
+count);
}
}
public static void main(
String[] args) {
Outside out=new Outside(10);
Inner inner=out.new Inner();
inner.showCount();
new Outside(20)
.new Inner().showCount();
}
}
În acest exemplu putem vedea cum metoda privată count din clasa Outside este accesibilă clasei Inner. Pentru crearea clasei Inner folosim constructorul implicit și de asemenea avem nevoie de o instanță a clasei de bază.
Ce facem în schimb dacă avem mai multe clase Inner înlănțuite? Vedem în următorul exemplu:
public class MoreInner {
private int count=0;
class Inner1{
private int count=10;
class Inner2{
private int count=20;
public void showAll(){
System.out.println(this.count);
System.out.println(
Inner1.this.count);
System.out.println(
MoreInner.this.count);
}
}
}
public static void main(
String[] args) {
new MoreInner().new Inner1()
.new Inner2().showAll();
}
}
Deși este un pic împinsă spre limită, suprascrierea variabilei count ne ajută să înțelegem mai bine modul de a fi referită o variabilă dintr-o clasă de bază. Modalitatea este:
Ex: Inner1.this.count
sau MoreInner.this.count
A se observa că doar în acest context de clasă Inner putem referi this către o referință statică a clasei. Încercarea de a face acest lucru în metoda main()
, de exemplu, va genera bineînțeles o eroare de compilare.
public class Park {
static class Ride {
private int price;
public Ride(int price){
this.price=price;
}
}
public static void main(
String[] args) {
var ride = new Ride(2);
System.out.println(ride.price);
System.out.println(new Ride(3).price);
}
}
Avantajul principal al claselor Inner statice este că nu mai avem nevoie de o instanță a clasei de bază pentru instanțiere. Chiar dacă clasele sunt declarate static, instanțele lor sunt diferite. În exemplul de mai sus vor fi afișate rezultatele 2 și 3.
public class PrintNumbers {
private int length = 5;
public void calculate() {
final int width = 20;
class Calculator {
public void multiply() {
System.out.print(length * width);
}
}
var calculator = new Calculator();
calculator.multiply();
}
public static void main(String[] args) {
new PrintNumbers().calculate();
}
}
Avantajul în cazul claselor Inner din metode este că putem separa logica internă și că avem acces la membrii clasei în care aceasta este declarată.
redButton.setOnAction(new EventHandler() {
public void handle(ActionEvent e) {
System.out.println(“Red button pressed!”);
}
});
Este o implementare clasică a unei interfețe printr-o clasă anonimă. Exemplul n-ar fi complet dacă nu am aminti și de prescurtările din metodele lambda:
public interface ActionInterface {
String justDoIt(String s);
}
public class AnonymousInner {
String makeNoise(ActionInterface action){
return action.justDoIt(“Hello”);
}
public static void main(String[] args) {
AnonymousInner inner=new AnonymousInner();
System.out.println(
inner.makeNoise((e)->{return “action:”+e;}));
System.out.println(
inner.makeNoise((e)->(“action:”+e)));
}
}
Ultimele două linii sunt echivalente.
Clasele Inner reprezintă în Java o modalitate rapidă de a încapsula logica aplicației noastre prin clase declarate în interiorul altor clase sau metode.