There is a noun around this chapter: Run-time Type Identification runtime type recognition
Someone knows that the author introduced this concept from C++, but it doesn't matter. Understanding and concatenating this chapter is the most important thing
The content of this chapter is actually for the type of information service, the main content is
Class Object
Question:
1. What is the process of creating Class objects
2. What are the ways Class objects are created and what are the differences between them
3. Use generics
Before you know the type information, you need to know the class object
To create a class object, you first need to look for the.Class file of this class. The class file you find will be loaded into memory as byte code, and then you can create all the objects of this class through the Class object in memory.
There are three ways to create objects in this chapter
First: via the new constructor
Second: Class cls = Class.forName("fully qualified name"); cls.newInstance();
The third type of Class cls =class:.class; cls.newInstance();
The second and third create objects through the virtual constructor newInstance(), which has two points to note: 1. interfaces cannot newInstance; 2. class must have empty constructors
What is the difference between these three ways, where other points of knowledge are involved?
1. Call a static method of a class, have you created an object
The answer is no, because there are no three ways to create objects, just load the.Class file into memory, initialize the class, and do not create objects.
public class Test { public static void main(String[] args) { // TODO Auto-generated method stub A.print(); } } class A{ static{ System.out.println("static Static block"); } public A(){ System.out.println("Construction method"); } public static void print(){ System.out.println("Print class A"); } }
The printed results are as follows:
static block
Print class A
2. Is there a difference between class.forName ("fully qualified name") and.class
In contrast, Class.forName actively loads static method blocks, whereas.class does not, and.class does not initialize static methods or non-constant static fields until they are first referenced
public static void main(String[] args) { // TODO Auto-generated method stub try { Class.forName("chapter_14.A"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
Print: static block
public static void main(String[] args) { // TODO Auto-generated method stub Class cls = A.class; }
No Print
To put it aside, why do we usually see static constants being accessed like this
public static final int CONSTANT = 5;
Instead of
public static int CONSTANT = 5;
The reason is that static final is a compile-time constant and the class. CONSTANT can be read without initializing the class
The significance of introducing generics is simply to provide compile-time checks. Chapter 15 focuses on generics, which provide several concepts
Unlike ordinary.class, generic newInstance() returns the exact type of the object
class A{} class B extends A{} Class<A> clsA = A.class; A objA = clsA.newInstance();
What about superclasses?
Class<? super B> clsA = B.class.getSuperclass(); Object objA = clsA.newInstance();
Superclass is not an exact type, it's just an Object
What about inheritance classes?
Class<? extends A> clsB = B.class; A objA = clsB.newInstance();
At this point, we get the type of parent class. In the next learning, we will often create objects in this way, which is polymorphic and type information.
2. Check before type conversion
Question:
1. Significance and method of checking before type conversion
Avoid ClassCastException by explicit downward transition
There are three common ways to check, instanceof, isInstance, isAssignableFrom
For instance:
class A implements Iface{} class B extends A{} interface Iface{}
The first instance of
//Class checks the type of object instantiated by its own class Class<? super B> clsA = B.class.getSuperclass(); Object objA = clsA.newInstance(); System.out.println(objA instanceof A);//true //Class Check Subclass Instantiation Object Type Class clsB = B.class; Object objB = clsB.newInstance(); System.out.println(objB instanceof A);//true //Interface check implements the type of class instantiation object System.out.println(objA instanceof Iface);//true System.out.println(objB instanceof Iface);//true
Second: isInstance
Class<? super B> clsA = B.class.getSuperclass(); Object objA = clsA.newInstance(); Class clsB = B.class; Object objB = clsB.newInstance(); //Class Class Object Check Instantiated Object of Class itself System.out.println(clsA.isInstance(objA));//true System.out.println(clsB.isInstance(objB));//true //Class Class Instantiated object of object check subclass System.out.println(clsA.isInstance(objB));//true //Interface Class Object Check Instantiated Object of Implementation Class Class clsIface = Iface.class; System.out.println(clsIface.isInstance(objA));//true System.out.println(clsIface.isInstance(objB));//true
Third isAssignable From
Class<? super B> clsA = B.class.getSuperclass(); Object objA = clsA.newInstance(); Class clsB = B.class; Object objB = clsB.newInstance(); //Class Class Object check class itself Class object System.out.println(clsA.isAssignableFrom(clsA));//true //Class Class Object Check Subclass Class object System.out.println(clsA.isAssignableFrom(clsB));//true //Interface Class Object Check Implementation Class Class object Class clsIface = Iface.class; System.out.println(clsIface.isAssignableFrom(clsA));//true System.out.println(clsIface.isAssignableFrom(clsB));//true
To summarize these three ways, here is the picture below.
On the other hand, type checking also illustrates the relationship between classes and classes, and between classes and interfaces.
3. Registered factories
Question:
1. What's the use of registering a factory?
Registered factories combine factory method design patterns with additions, whether in this chapter or in relation to type information, to add objects to the base class that implement the class, but only according to the factory design pattern. The benefit of doing so is to "avoid damage to the structure caused by newly added data".The examples in this chapter are impressive and very good, and if I have good examples, I will always link them
4. Empty Objects
Question:
1. What is an empty object
2. Meaning of using empty objects
Usually, an empty object is a singleton that has properties that cannot be modified
Assuming that a variable of a class is an empty object by default, if you want to change the properties of this variable, you need to re-create an object to replace the empty object. It feels like I'm saying nonsense, but this is the nature of an empty object. Consider the following code
interface Null{} class Person{ private final String first; private final String last; private final String address; public Person(String first, String last, String address) { super(); this.first = first; this.last = last; this.address = address; } @Override public String toString() { return "Person [first=" + first + ", last=" + last + ", address=" + address + "]"; } static class NullPerson extends Person implements Null{ private NullPerson(){ super("None", "None", "None"); } @Override public String toString() { return "NullPerson"; } } public static final Person NULL = new NullPerson(); }
This code is copied from the empty object section of Java programming thought, and there is another point of knowledge: not every class will have a default empty constructor, like the Person class above, there is no empty constructor. The problem is that the constructor's parameters are modified with final, so you can explore it.
5. Reflection
1. What is the reflection mechanism?
2. How to use reflection mechanism through dynamic proxy
Reflection is a program that opens and checks.Class files at run time, so reflection is dynamic, and the concept of reflection is supported in JDK using the Class class and java.lang.reflect class libraries
Reflection is used because there are attributes of certain classes, methods do not have package access, and we have to access them to do something
As you can imagine, package access does not work for reflection, including privates, private internal classes, and anonymous internal methods
Examples of applications to reflection are EventBus for component communication in android, which can be downloaded to see the source code
Reflection can also be used for dynamic proxies (to say more, dynamic proxies are essentially type information) The main code is copied from the book
public class Test { public static void main(String[] args) { A objA = new A(); Iface iface = (Iface) Proxy.newProxyInstance(Iface.class.getClassLoader(), new Class[]{Iface.class}, new DynamicProxyHandler(objA)); doSomething(iface); } public static void doSomething(Iface iface){ iface.doSomething(); } } class A implements Iface{ @Override public void doSomething() { System.out.println("A doSomething"); } } interface Iface{ public void doSomething(); } //All calls will be redirected to this single processor class DynamicProxyHandler implements InvocationHandler{ private Object proxied; public DynamicProxyHandler(Object proxy){ proxied = proxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return method.invoke(proxied, args); } }
There are three things to note here: 1. Redirect a single processor, what is the object invoked; 2. Create an iface must be an interface object, and the second parameter to pass to create an interface object is the Class array, which contains the interface name.class for all proxied; 3. Relationship between dynamic proxies and type information
Summary: Type information is essentially about upward or downward transition