In depth analysis of java reflection (II) – array and enumeration

premise

The java reflection API is in javase 1 7, but Oracle jdk11 was used when writing this article, because jdk11 also uploaded the source code under the sun package. You can directly view the corresponding source code and debug through the IDE.

This article mainly introduces two special types that may be used in reflection, array and enumeration, respectively corresponding to Java lang.reflect. Array and Java Lang. enum, the latter is not a class in the reflection class library package, but there are methods to use enumeration types in the reflection basic class library.

Array type

An array is a reference type object containing a fixed number of components of the same type, that is, the length of the array is immutable, and each element of it is of the same type. To create an array instance, you need to define the length of the array and the type of components. Array is implemented by Java virtual machine (this is very important, which is why there is no type corresponding to array in JDK class library, array is not a reserved keyword in Java, and the underlying methods for operating array are all native methods). Array types only inherit from Java Lang. object method, the length method of the array does not actually belong to the array type. In fact, the length method of the array finally calls Java lang.reflect. Array #getlength(), notice that this method is a native method. java. lang.reflect. Array is the core class based on reflection operation array.

The process of creating an array instance using non reflection is as follows:

fully_qualified_class_name[] variable_name  = {val1,val2,val3,...};

fully_qualified_class_name[] variable_name = new fully_qualified_class_name[${fix_length}];

例如:int[] arr = new int[10];

Using reflection is using Java lang.reflect. Related methods in array:

Class<?> c = Class.forName(cName);
Object o = Array.newInstance(c,n);
for (int i = 0; i < n; i++) {
    String v = cVals[i];
    Constructor ctor = c.getConstructor(String.class);
    Object val = ctor.newInstance(v);
    Array.set(o,i,val);
}
Object[] oo = (Object[]) o;

The following is a list of Java lang.reflect. Methods in array:

Some setter and getter methods for primitive types such as int and Boolean are omitted here.

In Java Lang. class and array related methods:

Here is an example to deepen the impression:

public class ArrayCreationMain {

	/**
	 * 这个是我们创建的最终目标数组
	 */
	private static String R = "java.math.BigInteger[] bi = {123,234,345}";
	private static final String[] S = new String[]{"123","234","345"};

	public static void main(String[] args) throws Exception {
		Class<BigInteger> componentType = BigInteger.class;
		Object arrayObject = Array.newInstance(componentType,3);
		for (int i = 0; i < S.length; i++) {
			String each = S[i];
			Constructor<BigInteger> constructor = componentType.getConstructor(String.class);
			BigInteger value = constructor.newInstance(each);
			Array.set(arrayObject,value);
		}
		Object[] result = (Object[]) arrayObject;
		System.out.println(String.format("%s[] = %s",componentType,Arrays.toString(result)));
		int length = Array.getLength(arrayObject);
		System.out.println("Length = " + length);
		for (int i = 0; i < length; i++) {
			System.out.println(String.format("index = %d,value = %s",Array.get(arrayObject,i)));
		}
		Class<?> arrayObjectClass = arrayObject.getClass();
		System.out.println("Is array type:" + arrayObjectClass.isArray());
		System.out.println("Component type:" + arrayObjectClass.getComponentType());
	}
}

Output after operation:

class java.math.BigInteger[] = [123,345]
Length = 3
index = 0,value = 123
index = 1,value = 234
index = 2,value = 345
Is array type:true
Component type:class java.math.BigInteger

It should be noted that Java lang.reflect. If the setter and getter methods in array operate array elements beyond the bounds, they will throw ArrayIndexOutOfBoundsException. Elements with different component types during setter setting and array initialization will throw illegalargumentexception.

On array types

We talked about some basic features of array types. Here are some advanced usage methods.

Create an array of specific element types:

Because of the problem of Java generic erasure, in fact, we can only get one result instance of object type by using the array#newinstance method. In fact, the type of this result instance is componenttype []. Here, only its parent class (object) type instance is returned, so we can directly enforce it, for example:

String[] strArray = (String[]) Array.newInstance(String.class,3);

Get array type:

In non - reflective mode, we can use array instances Class gets the array type directly through the class literal, for example:

Class stringArrayClass = String[].class;

Under reflection conditions, you can pass class Forname() gets the array type, but there is a restriction when calling this method. The class name must use the signature form recognized by the JVM, that is [l ${componenttype};. Note that class. Forname() cannot get the type of the original type (such as int and Boolean), for example:

// 不能漏了左边的[L和右边的;
Class stringArrayClass = Class.forName("[Ljava.lang.String;");

// 下面这样做会抛出ClassNotFoundException
Class intClass1 = Class.forName("I");
Class intClass2 = Class.forName("int");

Get array element (component) type:

At present, getting the array component type can only call class #getcomponenttype() through the array type instance.

Enumeration type

An enum is a language construct that is used to define type safe enumerations which can be used when a fixed set of named values is desired. All enumerations are inherited from Java lang.Enum。 An enumeration can contain one or more enumeration constants that are instances of the enumeration. The declaration of enumeration is actually similar to that of an ordinary class, because it can contain members such as fields, methods and constructors.

Because enumerations are ordinary Java classes, no Java is added to the reflection related class library lang.reflect. Enum type, API in reflection and enumeration related are:

If the member attribute in the instance is enumeration, the reflection operation of enumeration is actually Java lang.reflect. Field related operations.

for instance:

public class EnumerationMain {

	enum Color {
		RED,BLACK,BLUE
	}

	public static class ColorHolder {

		private Color color = Color.BLACK;

	}

	public static void main(String[] args) throws Exception {
		Class<Color> colorClass = Color.class;
		System.out.println("Color class is enum:" + colorClass.isEnum());
		System.out.println("Color values:" + Arrays.toString(colorClass.getEnumConstants()));
		ColorHolder colorHolder = new ColorHolder();
		Class<ColorHolder> holderClass = ColorHolder.class;
		Field field = holderClass.getDeclaredField("color");
		field.setAccessible(true);
		System.out.println("Old color:" + field.get(colorHolder));
		field.set(colorHolder,Color.RED);
		System.out.println("New color:" + field.get(colorHolder));
	}
}

Output after operation:

Color class is enum:true
Color values:[RED,BLUE]
Old color:BLACK
New color:RED

Previously, I wrote an article "the underlying implementation of enumeration in JDK", which translated the code logic of the class from the bytecode of the enumeration class. Here, turn out the example (mobile operating system enumeration) and say:

public enum PhoneOsEnum {

	/**
	 * 安卓
	 */
	ANDROID(1,"android"),/**
	 * ios
	 */
	IOS(2,"ios");


	private final Integer type;
	private final String typeName;

	PhoneOsEnum(Integer type,String typeName) {
		this.type = type;
		this.typeName = typeName;
	}

	public Integer getType() {
		return type;
	}

	public String getTypeName() {
		return typeName;
	}
}

This is the enumeration type we created using Java's syntax on enumeration. It is the Java class file we saw before compilation. In fact, after compilation, the enumeration type will become an ordinary Java class. It has the following characteristics:

That is, the phoneosenum mentioned above will become:

public final class PhoneOsEnumeration extends Enum<PhoneOsEnumeration> {

	public PhoneOsEnumeration(String name,int ordinal,Integer type,String typeName) {
		super(name,ordinal);
		this.type = type;
		this.typeName = typeName;
	}

	public Integer getType() {
		return type;
	}

	public String getTypeName() {
		return typeName;
	}

	public static PhoneOsEnumeration[] values() {
		return $VALUES.clone();
	}

	public static PhoneOsEnumeration valueOf(String name) {
		return Enum.valueOf(PhoneOsEnumeration.class,name);
	}
	
	private final Integer type;
	private final String typeName;
	public static final PhoneOsEnumeration ANDROID;
	public static final PhoneOsEnumeration IOS;
	private static final PhoneOsEnumeration[] $VALUES;

	static {
		ANDROID = new PhoneOsEnumeration("ANDROID",1,"android");
		IOS = new PhoneOsEnumeration("IOS",2,"ios");
		$VALUES = new PhoneOsEnumeration[]{ANDROID,IOS};
	}
}

In fact, if you write a Java class directly to inherit Java Lang. enum will compile and report errors, that is, Java wants to control the behavior and characteristics of enumeration by itself rather than developers, and control the type safety of enumeration from the compilation level. If you are more careful, you will find that valueof (string name) in enumeration is also determined by Java Provided by lang. class and traced back to the innermost layer is t [] Java Lang. class #getenumconstants() method may also be used when constructing the $values attribute. This point has not been studied further. Things at the compilation level may involve many aspects of knowledge, which has not yet reached that level.

Summary

Arrays and enumerations are also used frequently in Java, especially in algorithms or frameworks. This paper attempts to introduce the use of these two types from the perspective of reflection, and mastering them is very helpful to the use of arrays or enumerations.

Personal blog

(e-a-20181204)

The official account of Technology (Throwable Digest), which is not regularly pushed to the original technical article (never copied or copied):

Entertainment official account ("sand sculpture"), select interesting sand sculptures, videos and videos, push them to relieve life and work stress.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>