#博学谷IT学习技术支持#
1案例的类
import com.example.demo3.fanshe.MyAnnotation;
import lombok.Data;
/**
* @author zw
* @Description 描述
* @create /2022/2/13
*/
@MyAnnotation("Dog class Annotation")
@Data
public class Dog {
@MyAnnotation("Dog field-> name Annotation")
private String name="dog旺旺";
public String age="dog5岁";
protected String test="test岁";
String tesat="test岁";
//无参构造
public Dog(){
System.err.println("我是无参构造");
}
public void Dog(String age) {
this.age = age;
System.out.println("方法Dog 入参age"+age);
}
public void dog1(String age){
System.err.println("我是方法dog1:"+age);
}
public void dog1(String age,String name){
System.err.println("我是方法dog1==="+age+name);
}
//有参构造
public Dog(String age) {
this.age = age;
System.out.println("有参构造age"+age);
}
//有参构造
public Dog(String name, String age) {
this.name = name;
this.age = age;
System.out.println("有参构造name+age"+name+age);
}
@MyAnnotation(value = "Dog method Annotation")
public void testMyAnnotation(String name, String age) {
System.out.println("testMyAnnotation:"+name+age);
}
}
/**
* @author zw
* @Description 描述
* @create /2022/2/6
*/
//value 可以自动省略
//@Target(ElementType.METHOD)
@Target(value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented //表示把注解生成在Javadoc中
@Inherited //表示可以被继承
public @interface MyAnnotation {
String value();
}
2反射方法
2.1 获取class对象
//1三种获取反射方法
Dog dog = new Dog();
Class c1 = dog.getClass();//一般不用 因为反射效率低 都能new 对象了就不用反射了
System.out.println(c1.getName()); // com.example.demo3.fanseh.Dog
Class c2 =Dog.class;
Class c3 = Class.forName("com.example.demo3.fanseh.Dog");
System.out.println(c1==c2 == c3 );//true 因为内存中只有一份这个对象
2.2 获取方法
//2 反射获取所有方法 api
//获取所有public 修饰 方法
Method[] methods = c2.getMethods();
//获取指定方法 dog1方法 并且是public 修饰
Method method4 = c2.getMethod("dog1", String.class, String.class);
//调用dog1方法 后面两个是参数
method4.invoke(c2.newInstance(),"我是name入参","我是age入参");
//获取 public 修饰 所有构造方法
Constructor[] constructors = c2.getConstructors();
//获取所有的方法(包含private修饰的方法) 主要的
Method[] declaredMethods = c2.getDeclaredMethods();
for (Method method : declaredMethods) {
method.getName();//方法名
method.invoke(c2.newInstance(),"参数1","参数2");//执行方法
}
//获取指定的方法 参数一是方法名,后面是可变参,是参数类型
Method method1 = c2.getDeclaredMethod("dog1", String.class);
//参数一 类的实例 参数二 是参数 invoke执行这个方法
method1.invoke(c2.newInstance(),"参数");
手动拼接get/set方法
StringBuilder sb = new StringBuilder();
sb.append("get");
sb.append(fieldName.substring(0, 1).toUpperCase(Locale.ROOT));
sb.append(fieldName.substring(1));
2.3获取属性api
//3 获取所有的属性(包含private修饰的方法)
Field[] declaredFields = c2.getDeclaredFields();
Dog dog1 = new Dog();//需要赋值的对象
String str="反射赋值";
for (Field field : declaredFields) {
field.setAccessible(true);//解除私有限定 要不私有属性设置值等会报错
//获取属性名称
String name = field.getName();
String type = field.getType().toString();
if (type.endsWith("String")) {
field.set(dog1, str); // 给属性设值
} else if (type.endsWith("int") || type.endsWith("Integer")&&null!=str) {
field.set(dog1, new Integer((String) str)); // 给属性设值
} else if (type.endsWith("BigDecimal")&&null!=str) {
field.set(dog1, new BigDecimal((String) str)); // 给属性设值
} else if (type.endsWith("List")&&null!=str) {
field.set(dog1, str); // 给属性设值
} else {
field.set(dog1, str);
}
}
2.4 配合注解使用
//获取注解
// Dog类上是否含有这个注解
boolean annotation = c2.isAnnotationPresent(MyAnnotation.class);
System.err.println("Dog类是否含有注解:"+annotation);//是否含有注解:true
Method[] declaredMethods1 = c2.getDeclaredMethods();
for (Method method2 : declaredMethods1) {
//Dog类中 方法是否含有注解
boolean methodAnnotation = method2.isAnnotationPresent(MyAnnotation.class);
if(methodAnnotation){
MyAnnotation annotation2 = method2.getAnnotation(MyAnnotation.class);
System.out.println("注解的值"+annotation2.value());//注解的值Dog method Annotation
}
}
Field[] declaredFields1 = c2.getDeclaredFields();
Dog dog2 = new Dog();//需要赋值的对象
dog2.setName("反射获取值");
for (Field field : declaredFields1) {
boolean annotationPresent = field.isAnnotationPresent(MyAnnotation.class);
if(annotationPresent){
MyAnnotation annotation1 = field.getAnnotation(MyAnnotation.class);
System.out.println(annotation1.value());//Dog field-> name Annotation
field.setAccessible(true);//设置私有属性也能获取值
System.out.println(field.get(c2.newInstance()));//dog旺旺
System.out.println(field.get(dog2));//反射获取值
}
}
2.5获取属性值
Person person = new Person();
person.setId(1L);
person.setAge(12);
person.setMoney(new BigDecimal(0));
person.setName("小黄");
person.setAddress("北京");
Class c1 = person.getClass();
Field[] declaredFields = c1.getDeclaredFields();
List<Field> allFields = new ArrayList<>(100);
allFields.addAll(Arrays.asList(declaredFields));
allFields.forEach(field->{
field.setAccessible(true);
String name = field.getName();
try {
// 获取指定对象的当前字段的值
Object fieldVal = field.get(person);//1 小黄 12 北京 0
String value = name.substring(0, 1).toUpperCase() + name.substring(1);
Method method = c1.getMethod("get" + value);
// 获取指定对象的当前字段的值
Object fieldVal2= method.invoke(person);//1 小黄 12 北京 0
} catch (Exception | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
});
3 java反射内存图
引用别人内存图
4应用场景
1 一般的报表下载是最经常使用的(搭配自定义注解使用),看每个人封装能力和思维,封装的好,再也不用关心报表下载逻辑,只会关心数据的查询即可
2 框架的底层 ,这个一般是面试问到,所以要自己去学习,同时也是开阔思维,经典框架spring很有必要深入学习