学习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对象

操作属性

操作构造方法

操作方法

操作方法里的参数

操作方法里的返回值

操作泛型

操作注解

操作数组

重点:封装反射的工具类

相关推荐
西岸行者3 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意3 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码3 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习
im_AMBER4 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J4 天前
从“Hello World“ 开始 C++
c语言·c++·学习