java注解与反射02_反射

时间:2020-9-17 作者:admin

java注解与反射02_反射


正常方式:
引入需要的包类名称 –> 通过 new 实例化 –> 获得实例化对象

反射方式:
实例化对象 –> 通过 getClass() 方法 –> 得到完整的包类名称


User实体类:

package com.blu.demo6;

public class User{
	
	private String name;
	private int id;
	private int age;
	
	public User() {
		
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", id=" + id + ", age=" + age + "]";
	}	
	
	
}
package com.blu.demo6;

public class TestReflact {
	
	public static void main(String[] args) throws ClassNotFoundException {
		//通过反射获取类的Class对象
		Class<?> c1 = Class.forName("com.blu.demo6.User");
		Class<?> c2 = Class.forName("com.blu.demo6.User");
		Class<?> c3 = Class.forName("com.blu.demo6.User");
		System.out.println(c1.hashCode());
		System.out.println(c2.hashCode());
		System.out.println(c3.hashCode());
		
	}
}

hashcode一样,代表它们是同一个类(一个类在内存中有且只有一个Class对象)

366712642
366712642
366712642

Class类的常用方法:

static ClassforName(String name)		返回指定类名name的Class对象
Object newInstance()					调用缺省构造函数,返回Class对象的一个实例
getName()								返回此Class对象所表示的实体的名称
Class getSuperClass()					获得当前Class对象的父类Class对象
Class[] getinterfaces()					获取当前Class对象的接口
ClassLoader getClassLoder()				返回该类的类加载器
Constructor[] getConstructors()			返回一个包含某些Constructor对象的数组
Method getMethod(String name,Class.. T)	返回一个Method对象,此对象的形参类型为ParamType
Field[] getDeclaredFields()				返回Field对象的一个数组

三种方式获取Class类的实例:

方法1:通过类的class属性获取(安全可靠,性能最高)
Class clazz = User.class;

方法2:通过类的实例的getClass()方法获取
Class clazz = user.getClass();

方法3:已知类的全类名,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException异常
Class<?> c1 = Class.forName("com.blu.demo6.User");
public static void main(String[] args) throws ClassNotFoundException {
	//通过反射获取类的Class对象
	Class<?> c1 = Class.forName("com.blu.demo6.User");
	Class<?> c2 = User.class;
	User user = new User();
	Class<?> c3 = user.getClass();
	System.out.println(c1.hashCode());
	System.out.println(c2.hashCode());
	System.out.println(c3.hashCode());	
}
366712642
366712642
366712642

点1:每个基本内置类型的包装类都有一个Type属性,可通过该属性获取它的Class对象:

Class<Integer> type = Integer.TYPE;
System.out.println(type);
int

点2:通过 getSuperClass() 可以获取父类的Class对象:

Class<?> c1 = Class.forName("com.blu.demo6.User");
Class<?> superclass = c1.getSuperclass();
System.out.println(superclass);
class java.lang.Object

类加载内存分析:

类的加载:.class 字节码文件读入内存,并为之创建一个 java.lang.Class 对象,此过程由类加载器完成

类的链接: 将类的二进制数据合并到JRE中

  • 验证:验证类信息是否符合规范
  • 准备:为static变量分配内存(在方法区中)并设置默认初始值
  • 解析:将常量池中的符号引用(常量名)替换为直接引用(地址)

类的初始化:

初始化是执行类构造器的过程(类构造器是构造类信息的,不是构造类实例的那个构造器)
当初始化一个类时,需先初始化其父类

public class TestReflact2 {
	public static void main(String[] args) {
		A a = new A();
		System.out.println(A.m);
	}
}

class A{
	
	static {
		System.out.println("A类静态代码块初始化...");
		m = 300;
	}
	
	static int m = 100;
	
	public A() {
		System.out.println("A类的无参构造初始化...");
	}
}
A类静态代码块初始化...
A类的无参构造初始化...
100

java注解与反射02_反射
类加载器:

类加载器的作用:把类装载进内存中(在堆中生成一个代表该类的java.lang.Class对象)

引导类(根)加载器:用C++编写的JVM自带的类加载器,用于装载java核心类库 rt.jar,该加载器无法直接获取

扩展类加载器:负责 jre/lib/ext 目录下的jar包或 -D java.ext.dirs 指定目录下的jar包装入工作库

系统类(用户类)加载器:负责 java -classpath-D java.class.path 所指定的目录下的类与jar包装入工作,是最常用的加载器

public static void main(String[] args) throws ClassNotFoundException {
		
	//获取系统类(用户类)加载器
	ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
	System.out.println(systemClassLoader);
	
	//获取系统类加载器的父类 --> 扩展类加载器
	ClassLoader parent = systemClassLoader.getParent();
	System.out.println(parent);
	
	//获取扩展类加载器的父类 --> 根加载器(该加载器不能直接获取)
	ClassLoader parent2 = parent.getParent();
	System.out.println(parent2);
	
	//测试指定类是由哪个加载器加载的
	ClassLoader UserclassLoader = Class.forName("com.blu.demo6.User").getClassLoader();
	System.out.println(UserclassLoader);
	
	//测试jdk内部类是由哪个加载器加载的
	ClassLoader ObjectclassLoader = Class.forName("java.lang.Object").getClassLoader();
	System.out.println(ObjectclassLoader);

}
sun.misc.Launcher$AppClassLoader@73d16e93
sun.misc.Launcher$ExtClassLoader@15db9742
null
sun.misc.Launcher$AppClassLoader@73d16e93
null

双亲委派机制:

当一个Hello.class要被加载时。首先会在AppClassLoader中检查是否加载过,如果有就无需再加载了。如果没有,那么会到父加载器,检查父加载器是否已经加载过,如果没有再往上到达Bootstrap classLoader,如果父加载器无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。

双亲委派机制的好处:

如果有人想替换系统级别的类:java.lang.String.java,篡改它的实现,但是在这种机制下这些系统的类已经被Bootstrap classLoader加载过了,所以并不会再去加载,从一定程度上防止了危险代码的植入。


利用反射获取类的运行时结构:

package com.blu.demo6;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestReflact3 {
	
	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException {
		User user = new User();
		Class<? extends User> c1 = user.getClass();
		//获得类名
		System.out.println("获得类名================================");
		System.out.println(c1.getName());
		System.out.println(c1.getSimpleName());
		System.out.println("获得public属性================================");
		Field[] fs = c1.getFields();
		for (Field f : fs) {
			System.out.println(f);
		}
		System.out.println("获得全部属性(包括private属性)================================");
		Field[] fields = c1.getDeclaredFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		System.out.println("获得类的指定属性================================");
		Field name = c1.getDeclaredField("name");
		System.out.println(name);
		System.out.println("获得本类及其父类的全部public方法================================");
		Method[] methods = c1.getMethods();
		for(Method method : methods) {
			System.out.println(method);
		}
		System.out.println("获得本类的所有方法(包括private方法)================================");
		Method[] ms = c1.getDeclaredMethods();
		for(Method m : ms) {
			System.out.println(m);
		}
		System.out.println("获得指定方法================================");
		Method setName = c1.getMethod("setName", String.class);
		System.out.println(setName);
		
	}

}
获得类名================================
com.blu.demo6.User
User
获得public属性================================
获得全部属性(包括private属性)================================
private java.lang.String com.blu.demo6.User.name
private int com.blu.demo6.User.id
private int com.blu.demo6.User.age
获得类的指定属性================================
private java.lang.String com.blu.demo6.User.name
获得本类及其父类的全部public方法================================
public java.lang.String com.blu.demo6.User.toString()
public java.lang.String com.blu.demo6.User.getName()
public int com.blu.demo6.User.getId()
public void com.blu.demo6.User.setName(java.lang.String)
public void com.blu.demo6.User.setAge(int)
public void com.blu.demo6.User.setId(int)
public int com.blu.demo6.User.getAge()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
获得本类的所有方法(包括private方法)================================
public java.lang.String com.blu.demo6.User.toString()
public java.lang.String com.blu.demo6.User.getName()
public int com.blu.demo6.User.getId()
public void com.blu.demo6.User.setName(java.lang.String)
public void com.blu.demo6.User.setAge(int)
public void com.blu.demo6.User.setId(int)
public int com.blu.demo6.User.getAge()
获得指定方法================================
public void com.blu.demo6.User.setName(java.lang.String)

通过反射获取对象,并使用Method.invoke()方法动态执行指定对象的目标方法,通过Field.set()动态操作指定对象的目标属性:

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
	Class<?> c1 = Class.forName("com.blu.demo6.User");
	User user = (User) c1.newInstance();
	Method setName = c1.getDeclaredMethod("setName", String.class);
	setName.invoke(user, "BLU");
	System.out.println(user);
	Field age = c1.getDeclaredField("age");
	//操作私有的属性或方法之前需要先关闭程序的权限检测
	age.setAccessible(true);
	age.set(user, 23);
	System.out.println(user);
}
User [name=BLU, id=0, age=0]
User [name=BLU, id=0, age=23]

性能分析:

package com.blu.demo6;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestReflact4 {
	
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		test1();
		test2();
		test3();
	}
	
	public static void test1() {
		User user = new User();
		long startTime = System.currentTimeMillis();
		for(int i=0;i<1000000000;i++) {
			user.getName();
		}
		long endTime = System.currentTimeMillis();
		System.out.println("普通方式执行10亿次,花费时间:"+(endTime-startTime)+"ms");
	}
	
	public static void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		User user = new User();
		Class<? extends User> c1 = user.getClass();
		Method getName = c1.getDeclaredMethod("getName", null);
		long startTime = System.currentTimeMillis();
		for(int i=0;i<1000000000;i++) {
			getName.invoke(user, null);
		}
		long endTime = System.currentTimeMillis();
		System.out.println("反射方式执行10亿次,花费时间:"+(endTime-startTime)+"ms");
	}
	
	public static void test3() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		User user = new User();
		Class<? extends User> c1 = user.getClass();
		Method getName = c1.getDeclaredMethod("getName", null);
		getName.setAccessible(true);
		long startTime = System.currentTimeMillis();
		for(int i=0;i<1000000000;i++) {
			getName.invoke(user, null);
		}
		long endTime = System.currentTimeMillis();
		System.out.println("关闭安全检测后执行10亿次,花费时间:"+(endTime-startTime)+"ms");
	}
	
}
普通方式执行10亿次,花费时间:11ms
反射方式执行10亿次,花费时间:3311ms
关闭安全检测后执行10亿次,花费时间:1513ms

反射获取泛型信息:

package com.blu.demo6;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class TestReflact4 {
	
	public void test01(Map<String,User> map,List<User> list) {
		System.out.println("test01");
	}
	
	public Map<String,User> test02(){
		System.out.println("test02");
		return null;
	}
	
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		Method method1 = TestReflact4.class.getMethod("test01", Map.class,List.class);
		//获得形参参数类型
		Type[] genericParameterTypes = method1.getGenericParameterTypes();
		for(Type genericParameterType : genericParameterTypes) {
			System.out.println(genericParameterType);
			if(genericParameterType instanceof ParameterizedType) {
				Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
				for(Type actualTypeArgument : actualTypeArguments) {
					System.out.println(actualTypeArgument);
				}
			}
		}
		
		System.out.println("=======================================");
		
		Method method2 = TestReflact4.class.getMethod("test02", null);
		Type genericReturnType = method2.getGenericReturnType();
		if(genericReturnType instanceof ParameterizedType) {
			Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
			for(Type actualTypeArgument : actualTypeArguments) {
				System.out.println(actualTypeArgument);
			}
		}
	}

}
java.util.Map<java.lang.String, com.blu.demo6.User>
class java.lang.String
class com.blu.demo6.User
java.util.List<com.blu.demo6.User>
class com.blu.demo6.User
=======================================
class java.lang.String
class com.blu.demo6.User

反射获取注解信息:

package com.blu.demo6;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;

public class TestReflact5 {

	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
		
		//通过反射获得注解
		Class<?> c1 = Class.forName("com.blu.demo6.Student");
		Annotation[] annotations = c1.getAnnotations();
		for(Annotation annotation : annotations) {
			System.out.println(annotation);
		}
		
		//获取指定注解的值
		TableBLU tableBLU = c1.getAnnotation(TableBLU.class);
		System.out.println(tableBLU.value());
		
		Field f = c1.getDeclaredField("age");
		FieldBLU fieldBLU = f.getAnnotation(FieldBLU.class);
		System.out.println(fieldBLU.columnName());
		System.out.println(fieldBLU.type());
		System.out.println(fieldBLU.length());
		
	}
}

@TableBLU("t_student")
class Student{
	
	@FieldBLU(columnName="db_id",type="int",length=10)
	private int id;
	@FieldBLU(columnName="db_age",type="int",length=10)
	private int age;
	@FieldBLU(columnName="db_id",type="varchar",length=3)
	private String name;
	
	public Student() {
		
	}

	public Student(int id, int age, String name) {
		super();
		this.id = id;
		this.age = age;
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", age=" + age + ", name=" + name + "]";
	}
	
}

@Target(value=ElementType.TYPE)
@Retention(value=RetentionPolicy.RUNTIME)
@interface TableBLU{
	String value();
}

@Target(value=ElementType.FIELD)
@Retention(value=RetentionPolicy.RUNTIME)
@interface FieldBLU{
	String columnName();
	String type();
	int length();
}
@com.blu.demo6.TableBLU(value=t_student)
t_student
db_age
int
10
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。