Anonymous class (aiming to introduce stream api)

Purpose

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.

Nested class

Classes declared inside blocks ({}) are called "Nested Classes"

image.png 入れ子クラスのイメージ図.

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>

Inner class

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
  • ② You can access the instance variables defined in the outer class
① Cannot 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>

(2) You can access the instance variables defined in the outer class.

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
  • Inner class instance variable
  • Instance variable of external class

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

Anonymous class (anonymous class, anonymous inner class)

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

  • ① When the reusability of processing is low and it is necessary only on the spot
  • ② When the processing code is short but there is a lot of customization

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

Practical example of anonymous class

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

At the end

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