Get Class by reflection

Original link: https://www.codemore.top/cates/Backend/post/2018-04-26/reflect-class

kind

Every type in Java is either a reference type or a primitive type. Classes, enums, arrays (which they all inherit from java.lang.Object) and interfaces are all reference types. For example: java.lang.String, wrapper classes java.lang.Double, interfaces java.io.Serializableand enumerations javax.swing.Sortorderof all primitive types are reference types. The number of primitive types is fixed: boolean, byte, short, int, long, char, float, double. For each object type, the JVM initializes an java.lang.Classinstance of it and can inspect the properties of the object at runtime, including properties and methods. ClassIt is also possible to create a new class and object. Most importantly, it is the entry point for all reflection APIs.

get class object

java.lang.ClassIt is the entry point for all reflection operations. java.lang.reflectNone of the classes in . have a public constructor, so in order to instantiate one of them, you need to call the appropriate Classfunction.

Object.getClass()

If you can get an instance of a class, the easiest way to get Classit is to call Object.getClass(). ObjectOf course this only applies to reference types that all inherit from . StringFor example: returnedClass

Class c = "foo".getClass();

System.console() The return is a class, so the java.io.Consolefollowing code will knowConsoleClass

Class c = System.console().getClass();

For enumeration types, E, A is an instance of E, so what is A.getClass() returned is E. ClassFor example:

Enum E {A,B}
Class c = A.getClass();

getClass()Because the array is also an object, it can also be obtained by calling it Class, and the returned Classtype information with the array.

byte[] bytes = new byte[1024];
Class c = bytes.getClass();

For collection classes, the same s.getClass() return is java.util.HashSetrelated toClass

import java.util.Set
import java.util.HashSet

Set<String> s = new HashSet<String>();
Class c = s.getClass();
.class grammar

If the type is available, but there is no instance, it can be obtained .classby Class. Similarly, you can also use this method to get primitive types Class.

boolean b;
Class = b.getClass(); //编译错误

Class = boolean.class; //正确

Note that boolean.getClass()a compilation error will occur when using it directly, because it booleanis a primitive type and cannot be dereferenced.

Class c = java.io.PrintStream.class;

get java.io.PrintStreamrelatedClass

Class c = int[][].class;

Get the associated two-digit int arrayClass

Class.forName()

Using this method requires knowing the fully qualified name of the class. Can only be applied to reference types. The fully qualified name of the array type can be Class.getName()obtained by .

Class c = Class.forName("com.duke.MyLocaleServiceProvider");

Create a class by using the fully qualified name

Class cDoubleArray = Class.forName("[D");

Class cStringArray = Class.forName("[[Ljava.lang.String;");

cDoubleArrayYes double[]the Classsame double[].class. cStringArray is the String[][].classsame.

The TYPE field of the native type wrapper class

The native type Classcan be obtained either by .classmeans or through the TYPE field of the wrapper class of the native type. For void, java.lang.Voidsuch a field is also provided.

Class c = Double.TYPE;

Double.TYPE is equivalent todouble.class

Class c = Void.TYPE;

Equivalent tovoid.class

Methods that return Class

If it has been obtained Class, then you can use the API in Class to get other classes and  Class.getSuperClass() return the parent class of the specified class

Class c = javax.swing.JButton.class.getSupperClass();

Return to its parent class javax.swing.AbstractButton Class.getClasses() to get all internal public classes, interfaces, enumerations, including itself and inherited member classes.

Class<?>[] c = Character.class.getClasses();

Returns Charactertwo member classes Character.Subsetand Character.UnicodeBlock Class.getDeclearedClasses()returns all classes, interfaces, and enumerations in the class.

Class<?>[] c Character.class.getDeclearedClasses();

CharacterTwo public classes Character.Subsetand Character.UnicodeBlockone private class are returned Character.CharacterCacheClass.getDeclearingClass(), java.lang.reflect.Field.getDeclearingClass(), java.lang.reflect.Method.getDeclearingClass(), java.lang.reflect.Constructor.getDeclaringClass()returns the class that declares these members Returns the class that declares these members. An anonymous class does not have a declaring class, it has an enclosing class.

import java.lang.reflect.Field;

Field f = System.class.getField("out");
Class c = f.getDeclaringClass();

out is declared in System.

public class MyClass{
    static Object o = new Object() { public void m(){} }; static Class<c> = o.getClass().getEnclosingClass(); }

Class.getEnclosingClass() return its enclosing class

Class c = Thread.State.class.getEnclosingClass();

The outer class Thread of Thread.State

public class MyClass {
    static Object o = new Object() { public void m() {} }; static Class<c> = o.getClass().getEnclosingClass(); } 

The enclosing class of the anonymous class is MyClass.

There are three main methods for obtaining Class:

Way Scope of use
getClass() Need to get an object instance, can only be used for reference types
.class No need to get an instance of the object, either a reference type or a primitive type
forName () Only the fully qualified name of the class is required

Check for class modifiers and types

A class is declared with one or more modifiers that affect its runtime behavior:

  • Access modifiers: public, private, protected
  • Abstract modifier: abstract
  • static modifier: static
  • Immutable Modifier: final
  • Force strict floating point modifier: strictfp
  • Not all modifiers of annotations can be applied to all classes. For example, interface cannot use final, and enum cannot use abstract. java.lang.reflect.Modifier All modifier declarations are included. The method Class.getModifiers()can return all modifiers. The following example demonstrates how to obtain a class's modifiers, generic parameters, implementing interfaces, and integration chains. Because Classof inheritance java.lang.reflect.AnnotatedElement, annotation information can be obtained at runtime.
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List; import static java.lang.System.out; public class ClassDeclarationSpy { public static void main(String[] args) { try{ Class<?> c = Class.forName(args[0]); out.format("Class:%n %s%n%n", c.getCanonicalName()); out.format("Modifier: %n %s%n%n", Modifier.toString(c.getModifiers())); out.format("Type Parameters:%n"); TypeVariable[] tv = c.getTypeParameters(); if (tv.length != 0){ out.format(" "); for (TypeVariable t : tv) out.format("%s ", t.getName()); out.format("%n%n"); }else{ out.format("-- No TypeParameter --%n%n"); } out.format("Inheritance Path:%n"); List<Class> l = new ArrayList<>(); printAncestor(c, l); if (l.size() != 0) { for (Class<?> cl : l) out.format(" %s%n", cl.getCanonicalName()); out.format("%n"); } else { out.format(" -- No Super Classes --%n%n"); } out.format("Annotations:%n"); Annotation[] ann = c.getAnnotations(); if (ann.length != 0) { for (Annotation a : ann) out.format(" %s%n", a.toString()); out.format("%n"); } else { out.format(" -- No Annotations --%n%n"); } }catch (Exception e){ e.printStackTrace(); } } private static void printAncestor(Class<?> c, List<Class> l){ Class<?> ancestor =c.getSuperclass(); if (ancestor != null){ l.add(ancestor); printAncestor(ancestor, l); } } } 

run:

$ java ClassDeclarationSpy java.util.concurrent.ConcurrentNavigableMap
Class:
  java.util.concurrent.ConcurrentNavigableMap

Modifiers:
  public abstract interface

Type Parameters: K V Implemented Interfaces: java.util.concurrent.ConcurrentMap<K, V> java.util.NavigableMap<K, V> Inheritance Path: -- No Super Classes -- Annotations: -- No Annotations --

java.util.concrrent.ConcurrentNavigableMapThe source code is:

public interface ConcurrentNavigableMap<K,V> extends ConcurrentMap<K,V>, NavigableMap<K,V>

Note that, thinking that he is an interface, the compiler adds abstract to all interfaces by default. There are two generic types K, V. run:

$ java ClassDeclarationSpy "[Ljava.lang.String;"
Class:
  java.lang.String[]

Modifiers:
  public abstract final

Type Parameters:
  -- No Type Parameters --

Implemented Interfaces:
  interface java.lang.Cloneable interface java.io.Serializable Inheritance Path: java.lang.Object Annotations: -- No Annotations --]
get class members

There are two ways to get fields, methods, and constructors in Class, one is to get all members, and the other is to get specified members. The same way to get members is also divided into lookup from the current class and lookup from the inheritance chain. Summarized as follows: Field method

API list all members List inherited members private member
getDeclaredField() n n and
getField() n and n
getDeclaredFields() and n and
getFields() and and n

Method method

API list all members List inherited members private member
getDeclaredMethod() n n and
getMethod() n and n
getDeclaredMethods() and n and
getMethods() and and n

constructor method:

API list all members List inherited members private member
getDeclaredConstructor() n n and
getConstructor() n n n
getDeclaredConstructors() and n and
getConstructors() and n n

Constructors do not inherit.

An example is as follows:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Member;
import static java.lang.System.out; enum ClassMember { CONSTRUCTOR, FIELD, METHOD, CLASS, ALL } public class ClassSpy { public static void main(String... args) { try { Class<?> c = Class.forName(args[0]); out.format("Class:%n %s%n%n", c.getCanonicalName()); Package p = c.getPackage(); out.format("Package:%n %s%n%n", (p != null ? p.getName() : "-- No Package --")); for (int i = 1; i < args.length; i++) { switch (ClassMember.valueOf(args[i])) { case CONSTRUCTOR: printMembers(c.getConstructors(), "Constructor"); break; case FIELD: printMembers(c.getFields(), "Fields"); break; case METHOD: printMembers(c.getMethods(), "Methods"); break; case CLASS: printClasses(c); break; case ALL: printMembers(c.getConstructors(), "Constuctors"); printMembers(c.getFields(), "Fields"); printMembers(c.getMethods(), "Methods"); printClasses(c); break; default: assert false; } } // production code should handle these exceptions more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } } private static void printMembers(Member[] mbrs, String s) { out.format("%s:%n", s); for (Member mbr : mbrs) { if (mbr instanceof Field) out.format(" %s%n", ((Field)mbr).toGenericString()); else if (mbr instanceof Constructor) out.format(" %s%n", ((Constructor)mbr).toGenericString()); else if (mbr instanceof Method) out.format(" %s%n", ((Method)mbr).toGenericString()); } if (mbrs.length == 0) out.format(" -- No %s --%n", s); out.format("%n"); } private static void printClasses(Class<?> c) { out.format("Classes:%n"); Class<?>[] clss = c.getClasses(); for (Class<?> cls : clss) out.format(" %s%n", cls.getCanonicalName()); if (clss.length == 0) out.format(" -- No member interfaces, classes, or enums --%n"); out.format("%n"); } } 

Use as follows:

 java ClassSpy ClassMember FIELD METHOD
Class:
  ClassMember

Package:
  -- No Package --

Fields:
  public static final ClassMember ClassMember.CONSTRUCTOR
  public static final ClassMember ClassMember.FIELD public static final ClassMember ClassMember.METHOD public static final ClassMember ClassMember.CLASS public static final ClassMember ClassMember.ALL Methods: public static ClassMember ClassMember.valueOf(java.lang.String) public static ClassMember[] ClassMember.values() public final int java.lang.Enum.hashCode() public final int java.lang.Enum.compareTo(E) public int java.lang.Enum.compareTo(java.lang.Object) public final java.lang.String java.lang.Enum.name() public final boolean java.lang.Enum.equals(java.lang.Object) public java.lang.String java.lang.Enum.toString() public static <T> T java.lang.Enum.valueOf (java.lang.Class<T>,java.lang.String) public final java.lang.Class<E> java.lang.Enum.getDeclaringClass() public final int java.lang.Enum.ordinal() public final native java.lang.Class<?> java.lang.Object.getClass() public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final void java.lang.Object.wait() hrows java.lang.InterruptedException public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll()
Troubleshooting

The following examples are some common problems encountered when using annotations:

Compiler Warning: "Note: ... uses unchecked or unsafe operations"

When calling a method, the parameter type is checked rather than type conversion, as in the following example:

import java.lang.reflect.Method;

public class ClassWarning { void m() { try { Class c = ClassWarning.class; Method m = c.getMethod("m"); // warning // production code should handle this exception more gracefully } catch (NoSuchMethodException x) { x.printStackTrace(); } } }

operation result:

javac ClassWarning.java
Note: ClassWarning.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
$ javac -Xlint:unchecked ClassWarning.java
ClassWarning.java:6: warning: [unchecked] unchecked call to getMethod
  (String,Class<?>...) as a member of the raw type Class Method m = c.getMethod("m"); // warning ^ 1 warning

It can be solved by using generics or using annotations @SuppressWarning("unchecked"):

Class<?> c = warn.getClass();
Class c = ClassWarning.class;
@SupressWarning("unchecked")
Method m = c.getMethod();
InstantiationException when the Constructor is Not Accessible

If a class is created through Class.newInstance(), but there is no constructor with 0 parameters, an InstantiationException will be thrown. E.g:

class Cls {
    private Cls() {} } public class ClassTrouble { public static void main(String... args) { try { Class<?> c = Class.forName("Cls"); c.newInstance(); // InstantiationException // production code should handle these exceptions more gracefully } catch (InstantiationException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } catch (ClassNotFoundException x) { x.printStackTrace(); } } }

operation result:

java ClassTrouble
java.lang.IllegalAccessException: Class ClassTrouble can not access a member of
  class Cls with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65) at java.lang.Class.newInstance0(Class.java:349) at java.lang.Class.newInstance(Class.java:308) at ClassTrouble.main(ClassTrouble.java:9)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324899799&siteId=291194637