学习JavaEE的日子 Day39 注解,反射

Day39

注解

1.什么是注解

理解:给程序员和程序解释代码信息

2.注解与注释的区别

注释:对程序员解释代码信息

注解:对程序和程序员解释代码信息

3.注解的所用

可以作用于包、类、方法、属性上,给他们添加额外的信息,可以被其他程序(编译器)读取

4.注解的格式

注解是以"@注释名"在代码中存在的,还可以添加一些参数

例如:@SuppressWarnings(value="unchecked")

5.注解的应用

可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制实现对这些数据的访问

6.内置注解

理解:Java给我们提供个注解
*@Overrlde*:表示该方法是重写父类的方法
*@Deprecated*:表示该方法已过时
*@SuppressWarnings*:镇压警告,定义在java.lang.SuppressWarnings中用来抑制编译时的警告信息,与前两个注释有所不同.你需要添加参数才能正确使用。(镇压报小黄线的地方)

@SuppressWarnings("all")抑制所有类型的警告信息

@SuppressWarnings("unchecked")抑制单类型的警告信息

@SuppressWarnings(value={"unchecked","deprecation"})抑制多类型的警告信息

java 复制代码
public class Test01 {
	
	//@Override表示该方法是重写父类的方法
	@Override
	public String toString() {
		return super.toString();
	}
	
	//@Deprecated表示该方法已过时
	@Deprecated
	public void method01(){
	}
	
	//@SuppressWarnings表示镇压警告的注解
	@SuppressWarnings("all")
	public void method02(){
		
		ArrayList list = new ArrayList();
		list.add(100);
		list.add(123.123);
		list.add("用良心做教育");
	}
	
}

7.元注解

元注解的作用:负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
(@Target,@Retention,@Documented,@Inherited )
*@Target*:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

  • ElementType.TYPE 类上
  • ElementType.FIELD 属性上
  • ElementType.METHOD 方法上
  • ElementType.PARAMETER 参数上
  • ElementType.LOCAL_VARIABLE 局部变量上
  • ElementType.TYPE_PARAMETER 泛型上
    *@* *Retention*:表示需要要在什么级别保存该注择信息,用于描述注解的生命周期

SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在

CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值

RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

(SOURCE < CLASS < *RUNTIME*)
@Document:说明该注解将被包含在javadoc中
@lnherited:说明子类可以继承父类中的该注解

8.自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
分析:

@interface用来声明一个注解,格式:public @interface注解名{定义内容}

其中的每一个方法实际上是声明了一个配置参数.

方法的名称就是参数的名称.

返回值类型就是参数的类型(返回值只能是基本类型、Class、String、enum)

可以通过default来声明参数的默认值

如果只有一个参数成员,一般参数名为value()

注解元素必須要有值,我们定义注解元素时,经常使用空字符串.0作为默认值

java 复制代码
@MyAnnotaction
public class Test01<@MyAnnotaction T> {
	public static void main(String[] args) {
		
	}
	
	@MyAnnotaction
	String attr;

	@MyAnnotaction
	public static void method(@MyAnnotaction String str){
		
		@MyAnnotaction
		int i = 100;
		System.out.println(i);
	}
}

自定义注解类

java 复制代码
//@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE,ElementType.TYPE_PARAMETER})
//@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE,ElementType.TYPE_PARAMETER})
@Target({TYPE,FIELD,METHOD,PARAMETER,LOCAL_VARIABLE,TYPE_PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotaction {
}

注意:

当注解中只有"一个属性",并且属性名是"value",使用注解时,可以省略value属性名:public String value(); @Anno2("123")

反射

1.Java的反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
前言:

使用到一个类,JVM会将该类的class文件加载到方法区(类加载机制),同时会在堆内存中创建该类的class对象,class对象的作为class文件的访问入口
理解:

反射实际上就是获取class对象,通过class对象访问class文件中的内容
访问内容:属性;构造方法;普通方法(成员方法、静态方法、抽象方法...);方法上的参数;方法上的返回值;数组

注意:对于反射来说,一个类就是透明的,没有穿衣服的

2.关键点-获取Class文件对象

注意:

该类的class文件只在一次到方法区中,该类的class对象在程序中是唯一的。所以不管使用那种方式获取class对象都是同一个

java 复制代码
public class Test01 {
	public static void main(String[] args) throws ClassNotFoundException {
		
		//获取class对象方式1
		Class<? extends Student> clazz1 = Student.class;
		
		//获取class对象方式2
		Student stu = new Student();
		Class<? extends Student> clazz2 = stu.getClass();
		
		//获取class方式3(一般使用这个)
		Class<?> clazz3 = Class.forName("com.qf.reflex01.Student");
		
		System.out.println(clazz1 == clazz2);//true
		System.out.println(clazz1 == clazz3);//true
	}
}

经验:配置文件 + Class.forName() --常用

java 复制代码
public class Test02 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test02.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");
		
		Class<?> clazz = Class.forName(path);
	}
}

classPath.properties

properties 复制代码
path=com.qf.reflex01.Student

3.利用反射操作属性

Field[] getFields():返回所有成员变量对象的数组(只能拿public的)
Field[] getDeclaredFields():返回所有成员变量对象的数组,存在就能拿到
Field getField(String name):返回单个成员变量对象(只能拿public的)
Field getDeclaredField(String name):返回单个成员变量对象,存在就能拿到
注意:如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
获取成员变量并获取值和修改值

void set(Object obj, Object value):赋值

Object get(Object obj):获取值

java 复制代码
public class Test03 {
	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		
//		Properties p = new Properties();
//		p.load(Test03.class.getClassLoader().getResourceAsStream("classPath.properties"));
//		String path = p.getProperty("path");
		
//		Class<?> clazz = Class.forName(path);
		
		//获取本类及其父类公有的属性对象
//		Field[] fields = clazz.getFields();
//		for (Field field : fields) {
//			System.out.println(field);
//		}
		
		//获取本类所有的属性对象
//		Field[] fields = clazz.getDeclaredFields();
//		for (Field field : fields) {
//			System.out.println(field);
//		}
		
		//获取本类及其父类所有的属性对象
//		for(Class<?> c = clazz;c!=null;c=c.getSuperclass()){
//			Field[] fields = c.getDeclaredFields();
//			for (Field field : fields) {
//				System.out.println(field);
//			}
//		}
		
		
//		try {
//			//获取本类指定的属性对象
//			Field field = clazz.getDeclaredField("str");
//			System.out.println(field);
//			
//			//获取属性参数值
//			int modifiers = field.getModifiers();
//			System.out.println("是否使用public修饰:" + Modifier.isPublic(modifiers));
//			System.out.println("是否使用stati修饰:" + Modifier.isStatic(modifiers));
//			System.out.println("是否使用final修饰:" + Modifier.isFinal(modifiers));
//			System.out.println("是否使用private修饰:" + Modifier.isPrivate(modifiers));
//			System.out.println("是否使用protected修饰:" + Modifier.isProtected(modifiers));
//			System.out.println("是否使用transient修饰:" + Modifier.isTransient(modifiers));
//			
//		} catch (NoSuchFieldException e) {//属性名没有配到对应的属性就报该异常
//			e.printStackTrace();
//		} catch (SecurityException e) {
//			e.printStackTrace();
//		}
		
		//通过反射设置对象里的属性
//		Student stu = new Student("巴得伟", '男', 23, "2401", "001");
//		Field field = clazz.getDeclaredField("id");
//		field.setAccessible(true);//设置修改权限
//		field.set(stu, "666");//设置stu对象里的id属性为"666"的值
//		System.out.println(stu);
		
		//通过反射工具类设置对象里的属性
		Student stu = new Student();
		ReflexUtil.setField(stu, "name", "巴得伟");
		ReflexUtil.setField(stu, "sex", '男');
		ReflexUtil.setField(stu, "age", 23);
		ReflexUtil.setField(stu, "classId", "2401");
		ReflexUtil.setField(stu, "id", "001");
		
		System.out.println(stu);
	}
}

Person类

java 复制代码
package com.qf.reflex01;

public class Person {

	private String name;
	private char sex;
	private int age;
	
	//无参构造,有参构造,set,get省略
    
	@Override
	public String toString() {
		return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}
	
	protected static final synchronized void method(){
		System.out.println("静态方法");
	}
}

Person类的子类

java 复制代码
@MyAnnotaction(str = "aaa")
public class Student extends Person{
	
	private String classId;
	private String id;
	
	@MyAnnotaction(str = "bbb")
	public HashMap<String, Integer> map;
	
	public static final String str = "用良心做教育";

     //无参构造,有参构造,set,get省略 

	@Override
	public String toString() {
		return "Student [classId=" + classId + ", id=" + id + ", toString()=" + super.toString() + "]";
	}
	
	public void method01(){
		System.out.println("无参数无返回值的方法 -- method01");
	}
	
	public void method02(String str, int i){
		System.out.println("带参数的方法 -- method02:" + str + " -- " + i);
	}
	
	public String method03(){
		return "无参数带返回值的方法 -- method03";
	}
	
	private String method04(String str, int i){
		return "带参数带返回值的方法 -- method04:" + str + " -- " + i;
	}
	
	@MyAnnotaction(str = "ccc")
	public HashMap<Character, Boolean> method05(@MyAnnotaction(str = "ddd") ArrayList<Object> list,HashMap<Number, Double> map){
		return null;
	}
}

4.利用反射操作构造方法

Constructor[] getConstructors():获得所有的构造(只能public修饰)
Constructor[] getDeclaredConstructors():获得所有的构造(包含private修饰)
Constructor getConstructor(Class... parameterTypes):获取指定构造(只能public修饰)
Constructor getDeclaredConstructor(Class... parameterTypes):获取指定构造(包含private修饰)
newInstance():获取构造方法并创建对象的方法

java 复制代码
public class Test04 {
	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
//		Properties p = new Properties();
//		p.load(Test04.class.getClassLoader().getResourceAsStream("classPath.properties"));
//		String path = p.getProperty("path");
		
//		Class<?> clazz = Class.forName(path);
		
		//获取该类公有的构造方法对象
//		Constructor<?>[] constructors = clazz.getConstructors();
//		for (Constructor<?> constructor : constructors) {
//			System.out.println(constructor);
//		}
		
		//获取该类所有的构造方法对象
//		Constructor<?>[] constructors = clazz.getDeclaredConstructors();
//		for (Constructor<?> constructor : constructors) {
//			System.out.println(constructor);
//		}
		
		//获取无参构造对象
//		Constructor<?> constructor = clazz.getDeclaredConstructor();
//		//利用无参构造对象创建该类的对象
//		constructor.setAccessible(true);//设置修改权限
//		Student stu = (Student) constructor.newInstance();
//		System.out.println(stu);
		
		//利用无参构造对象创建该类的对象 -- 简化版
//		Student stu = (Student) clazz.newInstance();
//		System.out.println(stu);
		
		//获取有参构造对象
//		Constructor<?> constructor = clazz.getDeclaredConstructor(String.class,char.class,int.class,String.class,String.class);
//		//利用有参构造对象创建该类的对象
//		constructor.setAccessible(true);//设置修改权限
//		Student stu = (Student) constructor.newInstance("巴得伟",'男',23,"2401","001");
//		System.out.println(stu);
		
		//利用反射工具类去创建对象 -- 底层调用无参构造
//		Student stu = ReflexUtil.newInstance(Student.class, null, null);
//		System.out.println(stu);
		
		//利用反射工具类去创建对象 -- 底层调用有参构造
		Class<?>[] parameterTypes = {String.class,char.class,int.class,String.class,String.class};
		Object[] paremeters = {"巴得伟",'男',23,"2401","001"};
		Student stu = ReflexUtil.newInstance(Student.class, parameterTypes, paremeters);
		System.out.println(stu);
	}
}

5.利用反射操作方法

Method[] getMethods():返回所有成员方法对象的数组(只能拿public的)
Method[] getDeclaredMethods():返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name, Class... parameterTypes):返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod(String name, Class... parameterTypes):返回单个成员方法对象,存在就能拿到
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用

java 复制代码
public class Test01 {
	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException {
		
//		Properties p = new Properties();
//		p.load(Test01.class.getClassLoader().getResourceAsStream("classPath.properties"));
//		String path = p.getProperty("path");

//		Class<?> clazz = Class.forName(path);
		
		//获取本类及其父类公有的方法对象
//		Method[] methods = clazz.getMethods();
//		for (Method method : methods) {
//			System.out.println(method);
//		}
		
		//获取本类所有的方法对象
//		Method[] methods = clazz.getDeclaredMethods();
//		for (Method method : methods) {
//			System.out.println(method);
//		}
		
		//获取本类及其父类所有的方法对象
//		for (Class<?> c = clazz; c != null; c = c.getSuperclass()) {
//			Method[] methods = c.getDeclaredMethods();
//			for (Method method : methods) {
//				System.out.println(method);
//			}
//		}
		
		//获取本类公有的指定名字的方法对象
//		Method method = clazz.getMethod("setClassId", String.class);
//		System.out.println(method);
		
		//获取本类所有的指定名字的方法对象
//		Method method = clazz.getDeclaredMethod("method");
//		System.out.println(method);
		
		//利用反射工具类获取子类及其父类指定名字的方法对象
//		Method method = ReflexUtil.getMethod(clazz, "method");
//		System.out.println(method);
		//获取方法参数值
//		int modifiers = method.getModifiers();
//		System.out.println("是否使用public修饰:" + Modifier.isPublic(modifiers));
//		System.out.println("是否使用private修饰:" + Modifier.isPrivate(modifiers));
//		System.out.println("是否使用protected修饰:" + Modifier.isProtected(modifiers));
//		System.out.println("是否使用static修饰:" + Modifier.isStatic(modifiers));
//		System.out.println("是否使用final修饰:" + Modifier.isFinal(modifiers));
//		System.out.println("是否使用abstract修饰:" + Modifier.isAbstract(modifiers));
//		System.out.println("是否使用synchronized修饰:" + Modifier.isSynchronized(modifiers));
		
	}
}

6.利用反射操作方法

java 复制代码
public class Test02 {
	public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		
		Properties p = new Properties();
		p.load(Test02.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
//		//利用反射调用静态方法
//		Method method = ReflexUtil.getMethod(clazz, "method");
//		method.invoke(null);//静态方法不需要对象调用,就传入null
//		
//		Student stu = new Student();
//		
//		//利用反射调用成员方法 -- 无参数无返回值的方法
//		Method method01 = ReflexUtil.getMethod(clazz, "method01");
//		method01.invoke(stu);
//	
//		//利用反射调用成员方法 -- 带参数的方法
//		Method method02 = ReflexUtil.getMethod(clazz, "method02", String.class,int.class);
//		method02.invoke(stu, "用良心做教育",100);
//		
//		//利用反射调用成员方法 -- 无参数带返回值的方法
//		Method method03 = ReflexUtil.getMethod(clazz, "method03");
//		String returnVal1 = (String) method03.invoke(stu);
//		System.out.println(returnVal1);
//		
//		//利用反射调用成员方法 -- 带参数带返回值的方法
//		Method method04 = ReflexUtil.getMethod(clazz, "method04", String.class,int.class);
//		method04.setAccessible(true);//设置修改权限
//		String returnVal2 = (String) method04.invoke(stu, "用良心做教育",200);
//		System.out.println(returnVal2);
		
		//利用反射工具类 -- 调用静态方法
		ReflexUtil.invoke(clazz, "method", null, null);
		
		Student stu = new Student();
		
		//利用反射工具类 -- 反射调用成员方法 -- 无参数无返回值的方法
		ReflexUtil.invoke(stu, "method01", null, null);
		
		//利用反射工具类 -- 反射调用成员方法 -- 带参数的方法
		ReflexUtil.invoke(stu, "method02", new Class[]{String.class,int.class}, new Object[]{"用良心做教育",100});
		
		//利用反射工具类 -- 反射调用成员方法 -- 无参数带返回值的方法
		Object returnVal1 = ReflexUtil.invoke(stu, "method03", null, null);
		System.out.println(returnVal1);
		
		//利用反射工具类 -- 反射调用成员方法 -- 带参数带返回值的方法
		Object returnVal2 = ReflexUtil.invoke(stu, "method04", new Class[]{String.class,int.class}, new Object[]{"用良心做教育",100});
		System.out.println(returnVal2);
	}
}

7.利用反射操作 方法里的参数和返回值

java 复制代码
public class Test03 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test03.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
		//利用反射工具类获取方法对象
		Method method = ReflexUtil.getMethod(clazz, "method04", String.class,int.class);
		
		//获取方法的参数个数
		int parameterCount = method.getParameterCount();
		System.out.println("获取方法的参数个数:" + parameterCount);
		
		System.out.println("-----------------------------");
		
		//获取方法参数的class对象数组
		Class<?>[] parameterTypes = method.getParameterTypes();
		for (Class<?> c : parameterTypes) {
			System.out.println(c);
		}
		
		System.out.println("-----------------------------");
		
		//获取方法参数的Type对象数组
		//一个参数类型就是一个Type对象
		Type[] genericParameterTypes = method.getGenericParameterTypes();
		for (Type type : genericParameterTypes) {
			System.out.println(type);
		}
		
		System.out.println("-----------------------------");
		
		//获取方法参数对象数组
		//一个参数就是一个参数对象
		Parameter[] parameters = method.getParameters();
		for (Parameter parameter : parameters) {
			
			System.out.println("获取方法的参数类型:" + parameter.getType());
			
			/**
			 * 注意:
			 * 		参数名不会随着编译而编译到class文件,
			 * 		class文件描述该方法的参数名使用的是:arg0,arg1,arg2,.....
			 */
			System.out.println("获取方法的参数名:" + parameter.getName());
		}
		
		System.out.println("-----------------------------");
		
		//获取返回值的class对象
		Class<?> returnType = method.getReturnType();
		System.out.println("获取返回值的class对象:" + returnType);
		
		//获取返回值的Type对象
		Type genericReturnType = method.getGenericReturnType();
		System.out.println("获取返回值的Type对象:" + genericReturnType);
	}
}

8.利用反射操作泛型

注意:

集合中的泛型只在java文件中存在,当编译成class文件之后,就没有泛型了。

类上的泛型是获取不到的,因为不固定!!!

class A{}

java 复制代码
public class Test04 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test04.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
		
		//获取属性上的泛型类型
		Field field = ReflexUtil.getField(clazz, "map");
		Type fieldType = field.getGenericType();
		ParameterizedType fieldTypepPT = (ParameterizedType) fieldType;
		Type[] actualTypeArguments = fieldTypepPT.getActualTypeArguments();//获取泛型类型
		for (Type type : actualTypeArguments) {
			System.out.println(type);
		}
		
		System.out.println("---------------------------------------");
		
		Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class);
		
		//获取方法上参数的泛型类型
		Parameter[] parameters = method.getParameters();
		for (Parameter parameter : parameters) {
			Type parameterizedType = parameter.getParameterizedType();
			ParameterizedType parameterTypepPT = (ParameterizedType) parameterizedType;
			Type[] actualTypeArguments2 = parameterTypepPT.getActualTypeArguments();
			for (Type type : actualTypeArguments2) {
				System.out.println(type);
			}
		}
		
		System.out.println("---------------------------------------");
		
		//获取方法上返回值的泛型类型
		Type genericReturnType = method.getGenericReturnType();
		ParameterizedType returnPT = (ParameterizedType) genericReturnType;
		Type[] actualTypeArguments2 = returnPT.getActualTypeArguments();
		for (Type type : actualTypeArguments2) {
			System.out.println(type);
		}
	}
}

9.利用反射操作注解

java 复制代码
public class Test05 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test05.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
		//获取类上的注解信息
		MyAnnotaction classAnnotation = clazz.getAnnotation(MyAnnotaction.class);
		System.out.println(classAnnotation.str());
	
		System.out.println("------------------------------------------------");
		
		//获取属性上的注解信息
		Field field = ReflexUtil.getField(clazz, "map");
		MyAnnotaction fieldAnnotation = field.getAnnotation(MyAnnotaction.class);
		System.out.println(fieldAnnotation.str());
		
		System.out.println("------------------------------------------------");
		
		//获取方法上的注解信息
		Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class);
		MyAnnotaction methodAnnotation = method.getAnnotation(MyAnnotaction.class);
		System.out.println(methodAnnotation.str());
		
		System.out.println("------------------------------------------------");
		
		//获取参数上的注解信息
		Parameter[] parameters = method.getParameters();
		for (Parameter parameter : parameters) {
			MyAnnotaction parameterAnnotation = parameter.getAnnotation(MyAnnotaction.class);
			if(parameterAnnotation != null){//说明该参数上有MyAnnotaction的注解
				System.out.println(parameterAnnotation.str());
			}
		}	
		
	}
}

MyAnnotaction类

java 复制代码
@Target({TYPE,FIELD,METHOD,PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotaction {
	
	String str();
	
}

10.利用反射操作数组

注意:Array -- 该类是Java给我们提供专门利用反射去操作数组的类

java 复制代码
public class Test06 {
	public static void main(String[] args) {
		
		//创建数组
		int[] arr = (int[]) Array.newInstance(int.class, 10);
		
		//获取数组长度
		int length = Array.getLength(arr);
		System.out.println("获取数组长度:" + length);
		
		//循环设置每个下标上的元素
		for (int i = 0; i < Array.getLength(arr); i++) {
			//设置当前下标上的元素
			Array.set(arr, i, i+1);
		}
		
		//循环获取每个下标上的元素
		for (int i = 0; i < Array.getLength(arr); i++) {
			//获取当前下标上的元素
			Object element = Array.get(arr, i);
			System.out.println(element);
		}
	}
}

10.反射工具类

java 复制代码
package com.qf.utils;

public class ReflexUtil {

	/**
	 * 获取当前类及其父类的属性对象
	 * @param clazz class对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static Field getField(Class<?> clazz,String name){
		
		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
			try {
				Field field = c.getDeclaredField(name);
				return field;
			} catch (NoSuchFieldException e) {
			} catch (SecurityException e) {
			}
		}
		return null;
	}
	
	/**
	 * 设置对象中的属性
	 * @param obj 对象
	 * @param name 属性名
	 * @param value 属性值
	 */
	public static void setField(Object obj,String name,Object value){
		
		Field field = getField(obj.getClass(), name);
		if(field != null){
			field.setAccessible(true);
			try {
				field.set(obj, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建对象
	 * @param clazz class对象
	 * @param paremeterType 构造方法中的参数类型数组
	 * @param paremeters 构造方法中的参数数据
	 * @return 对象
	 */
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
		
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T obj = constructor.newInstance(paremeters);
			return obj;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取方法对象
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @return 方法对象
	 */
	public static Method getMethod(Class<?> clazz,String name,Class<?>... parameterTypes){
		
		for(Class<?> c = clazz; c != null; c = c.getSuperclass()) {
			try {
				Method method = c.getDeclaredMethod(name, parameterTypes);
				return method;
			} catch (NoSuchMethodException e) {
			} catch (SecurityException e) {
			}
		}
		
		return null;
	}

	/**
	 * 调用成员方法
	 * @param obj 对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Object obj,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Class<? extends Object> clazz = obj.getClass();
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(obj, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
	
	/**
	 * 调用静态方法
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Class<?> clazz,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(null, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
}

简答题

1.获取Class实例的方式

类名.class

对象.getClass

类的全限定类名
2.如何通过反射创建类对象

Class aClass = Class.forName();

Constructor c = aClass.getConstructor(String.class);

Object o = c.newInstance("hello");
3.如何通过反射调用方法、设置字段

Method method = aClass.getMethod("print",String.class);

Object h = method.invoke(o,"你好");

Field field = aClass.getField("username");

field.set(o,"Tom");

Object f = field.get(o);
4.反射机制的优缺点:

优点:

1)能够运行时动态获取类的实例,提高灵活性;

2)与动态编译结合

缺点:

1)使用反射性能较低,需要解析字节码,将内存中的对象进行解析。

2)相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)
5.哪里会用到反射机制?

jdbc就是典型的反射

java 复制代码
Class.forName('com.mysql.jdbc.Driver.class');//加载MySQL的驱动类

这就是反射。如hibernate,struts等框架使用反射实现的。

总结

反射

获取class对象

操作属性

操作构造方法

操作方法

操作方法里的参数

操作方法里的返回值

操作泛型

操作注解

操作数组

重点:封装反射的工具类

相关推荐
Theodore_10222 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
朝九晚五ฺ5 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
猫爪笔记7 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
pq113_67 小时前
ftdi_sio应用学习笔记 3 - GPIO
笔记·学习·ftdi_sio
澄澈i7 小时前
设计模式学习[8]---原型模式
学习·设计模式·原型模式
爱米的前端小笔记8 小时前
前端八股自学笔记分享—页面布局(二)
前端·笔记·学习·面试·求职招聘
alikami8 小时前
【前端】前端学习
学习
一只小菜鸡..8 小时前
241118学习日志——[CSDIY] [ByteDance] 后端训练营 [06]
学习
Hacker_Oldv10 小时前
网络安全的学习路线
学习·安全·web安全
蒟蒻的贤10 小时前
vue学习11.21
javascript·vue.js·学习