I felt that understanding the concept of designing and implementing anonymous classes was essential for learning the stream api. Method reference, functional interface, lambda expression, design using generics (instance scope and method scope, design based on PECS principle) Learn about anonymous inner classes that are the entry point before learning.
Classes declared inside blocks ({}) are called "Nested Classes"
入れ子クラスのイメージ図.
NastedClazzSample.java
public class NastedClazzSample {
static class StaticClazz {} //static member class
class MemberClazz {} //menber class (inner class)
void method() {
class LocalClazz {} //local class (inner class)
}
}
Nested classes declared as member classes can have access modifiers
NastedClazzSample.java
public class NastedClazzSample {
static protected class StaticClazz {} // OK
private class MemberClazz {} // OK
void method() {
public class LocalClazz {} // NG
}
}
Error.java
The qualifier for the local class LocalClazz is incorrect. Only abstract or final allowed NastedClassSample.java /...(path)Line 11 Java problem
For some reason. The scope of local classes is similar to local variables In the example, access LocalClazz via method () In other words, it is the same as the accessor of method (), so it is not possible to describe it. </ Font>
As mentioned above, nested classes (non-static member classes) other than static member classes are called inner classes.
Inner class features
- ① Can't have static members
Non-static members are associated with instances Local variables are managed in the stack area and placed in the heap area when the target class is instantiated.
InnerClazzSample.java
public class InnerClazzSample {
public class Inner {
String foo;
}
public static void main(String... args) {
Inner inner = new InnerClazzSample().new Inner();
inner.foo = "bar";
System.out.println(inner.foo);
}
}
Execution result.java
bar
When used without instantiation
InnerClazzSample.java
public class InnerClazzSample {
public class Inner {
String foo;
}
public static void main(String... args) {
Inner.foo = "bar";
}
}
Error.java
Non-static field Inner.Unable to statically reference foo InnerClazzSample.java /~(path)Line 9 Java problem
What is the meaning of this.
First, the JVM reads the classes used by the application and deploys them in memory. At this time, the static member is placed in a memory area (class area) different from the non-static member. The bootstrap class loader is called at JVM startup, but instead of loading all the classes, it is loaded when there is a class reference from the application. You can also change the range of class sets that can be loaded by changing -Xbootclasspath.
static members are associated with classes. The timing of expansion into memory depends on the JVM implementation. </ Font>
Outer.java
public class Outer {
private int foo;
public class Inner {
public int bar;
private void method() {
this.foo = Outer.this.bar; // OK
}
}
private void method() {
this.foo = bar; // NG
}
}
Also, the instance priority of non-static inner classes is
- Caller local variable
Outer.java
public class Outer {
String foo = "outerclass-a";
String bar = "outerclass-b";
String baz = "outerclass-c";
public class Inner {
String foo = "innerclass-a";
String bar = "innerclass-b";
public void thread() {
String foo = "thread-c";
System.out.println(foo);
System.out.println(bar);
System.out.println(baz);
System.out.println(this.foo);
System.out.println(Outer.this.foo);
}
}
public static void main(String... args) {
new Outer().new Inner().thread();
}
}
Execution result.java
thread-c
innerclass-b
outerclass-c
innerclass-a
outerclass-a
When using a nested class, it can be used as a class without a name Such nested classes are called "anonymous classes"
Mainly used for the following purposes
Anonymous class-Syntax 1.text
new type name() {
Implementation of abstract methods
}
Anonymous class-Syntax 2.text
Type name Instance name=new type name() {
Implementation of abstract methods
}
First, implement the interface abstract method without using anonymous class.
Sample.java
interface FooInterface { //interface
void method(); //abstract method
}
class BarClazz implements FooInterface { //implemented class
public void method() {
System.out.println("Did Implementation"); //implemented abstract method
}
}
public class Sample{ //runner
public static void main(String... args) {
new BarClazz().method(); //new instance
}
}
When implementing an abstract method using an anonymous class
Sample.java
interface FooInterface {
void method();
}
//nothing inplemented class
public class Sample {
public static void main(String... args) {
FooInterface foo = new FooInterface() { //anonymous class
public void method() {
System.out.println("Did Implementation"); //implemented abstract method
}
}; //semi-coron
foo.method(); //instance.method()
}
}
Execution result.java
Did Implementation
Consider a practical example of an anonymous class
(1) When the reusability of processing is low and it is necessary only on the spot
Define a class that manages customer information
ManagementClientInformation.java
public class ManagementClientInformation {
public static class Client {
private int id;
private String name;
Client(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
public static void main(String... args) {
List<Client> clientList = new ArrayList<>();
clientList.add(new Client(1, "matsuda"));
clientList.add(new Client(2, "tanaka"));
clientList.add(new Client(3, "neko"));
clientList.stream()
.forEach(x -> System.out.println(x.getId() + " " + x.getName()));
}
}
Execution result.java
1 matsuda
2 tanaka
3 neko
Consider the following events
You are a system engineer There was a request from a customer during maintenance / repair There is a request to sort a certain screen in reverse order of customer id In addition, it is prohibited to modify the Client class due to concerns about system impact and bloat.
⇒ Use anonymous class
ManagementClientInformation.java
public class ManagementClientInformation {
public static class Client {
private int id;
private String name;
Client(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
public static void main(String... args) {
List<Client> clientList = new ArrayList<>();
clientList.add(new Client(1, "matsuda"));
clientList.add(new Client(2, "tanaka"));
clientList.add(new Client(3, "neko"));
Collections.sort(clientList, new Comparator<Client>() {
public int compare(Client c1, Client c2) {
return Integer.compare(c2.getId(), c1.getId());
}
});
clientList.stream()
.forEach(x -> System.out.println(x.getId() + " " + x.getName()));
}
}
Execution result.java
3 neko
2 tanaka
1 matsuda
When I first touched the Stream api, I didn't understand the contents at all. While I was doing it, I gradually deepened my understanding as I learned the method reference ⇒ lambda expression ⇒ generics design in the reverse order. I would like to apply it after understanding the basic part firmly.
Recommended Posts