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

news/2024/9/26 1:23:36/

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”})抑制多类型的警告信息

public class Test01 {//@Override表示该方法是重写父类的方法@Overridepublic String toString() {return super.toString();}//@Deprecated表示该方法已过时@Deprecatedpublic 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作为默认值

@MyAnnotaction
public class Test01<@MyAnnotaction T> {public static void main(String[] args) {}@MyAnnotactionString attr;@MyAnnotactionpublic static void method(@MyAnnotaction String str){@MyAnnotactionint i = 100;System.out.println(i);}
}

自定义注解

//@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对象都是同一个

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

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

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

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):获取值

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类

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

Person类的子类

@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省略 @Overridepublic 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():获取构造方法并创建对象的方法

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):返回单个成员方法对象,存在就能拿到

如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用

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.利用反射操作方法

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.利用反射操作 方法里的参数和返回值

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{}

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.利用反射操作注解

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类

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

10.利用反射操作数组

注意:Array – 该类是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.反射工具类

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就是典型的反射

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

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

总结

反射

获取class对象

操作属性

操作构造方法

操作方法

操作方法里的参数

操作方法里的返回值

操作泛型

操作注解

操作数组

重点:封装反射的工具类


http://www.ppmy.cn/news/1426757.html

相关文章

[Qt网络编程]之获取基本网络信息

目录 前言 获取主机IP地址 获取主机 IP 地址和子网掩码 获取主机 MAC 地址 前言 获取主机的网络地址和接口信息是进行网络编程的第一步&#xff0c;也是网络编程的基础。Qt提供了网络接口类 QNetworkInterface、网络地址人口类 QNetworkAddressEntry 和主机地址类 QHostAd…

链表经典算法OJ题目

1.单链表相关经典算OJ题目1&#xff1a;移除链表元素 思路一 直接在原链表里删除val元素&#xff0c;然后让val前一个结点和后一个节点连接起来。 这时我们就需要3个指针来遍历链表&#xff1a; pcur —— 判断节点的val值是否于给定删除的val值相等 prev ——保存pcur的前…

Blender生成COLMAP数据集

最近在做3DGS方向&#xff0c;整理了一下Blender生成自己的数据集。 1 Introduction 在Blender中构建场景&#xff08;light, object, camera&#xff09;&#xff0c;利用Blender的python脚本对其渲染&#xff0c;导出多视角下渲染出的RGB图和depth map&#xff0c;并将trans…

对单片机的一点理解

前言 大一时学过一段时间的51单片机&#xff0c;后面就一直研究STM32和算法&#xff0c;最近工作搞51单片机有半年了&#xff0c;有一些自己的想法&#xff0c;跟公司的工程师也探讨了一些&#xff0c;结合聊天记录&#xff0c;写了这篇博客&#xff0c;希望对读者有帮助。 有…

新型大数据架构之湖仓一体(Lakehouse)架构特性说明——Lakehouse 架构(一)

文章目录 为什么需要新的数据架构&#xff1f;湖仓一体&#xff08;Lakehouse&#xff09;——新的大数据架构模式同时具备数仓与数据湖的优点湖仓一体架构存储层计算层 湖仓一体特性单一存储拥有数据仓库的查询性能存算分离开放式架构支持各种数据源类型支持各种使用方式架构简…

面试八股——集合——List

主要问题 数组 如果数组索引从0开始时&#xff0c;数组的寻址方式为&#xff1a; 如果数组索引从1开始时&#xff0c;数组的寻址方式为&#xff1a; 此时对于CPU来说增加了一个减法指令&#xff0c;降低寻址效率。 ArrayList⭐ ArrayList构造函数 尤其说一下第三个构造函数流…

js删除对象中值为null的属性

需求&#xff1a;在做编辑操作的时候&#xff0c;后端不需要值为null的数据&#xff0c;所以默认把编辑中值为null的数据传给他会编辑失败&#xff0c;所以前端做个筛选就行了 let obj {id: 1,name: "翠花",sex: 18,hobby: null,age: null,};// 使用Object.entries(…

游戏开发过程中,什么情况下用组件

在游戏开发过程中&#xff0c;使用组件的情境是多种多样的&#xff0c;它们主要用于实现游戏的各种功能和特性。以下是一些常见的情况&#xff0c;在这些情况下使用组件是非常合适的&#xff1a; 实体属性与行为分离 当需要将游戏实体的属性&#xff08;如位置、速度、…