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对象
操作属性
操作构造方法
操作方法
操作方法里的参数
操作方法里的返回值
操作泛型
操作注解
操作数组
重点:封装反射的工具类