概述
目录
1反射机制的作用
2.获取Class对象
3.获取类的构造方法并使用
4.获取类的成员变量并使用
5.获取类的成员方法并使用
6.检查类的结构
7.在运行时使用反射分析对象
8.使用反射可以编写泛型的数组
9.调用任意方法
1反射机制的作用
2.获取Class对象
为什么第三种是常用的?如果我们拿到了类实例还用getClass()方法去创建就显得有些多余,第二种需要引入对象的依赖,如果没有对象的包就完了。
3.获取类的构造方法并使用
4.获取类的成员变量并使用
含有Declare的方法是能够无视访问修饰符,拿到所有的字段,但是不包括继承的,不含Declare的方法能够拿到公开的,包括继承的。
5.获取类的成员方法并使用
6.检查类的结构
现在有两个类
package com.wx1.test4;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* User: Mr.Wang
* Date: 2019/10/27
*/
public class Employee {
private String name;
private Double salary;
private LocalDateTime hireDay;
public Employee(){
}
public Employee(String name, Double salary, LocalDateTime hireDay) {
this.name = name;
this.salary = salary;
this.hireDay = hireDay;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public LocalDateTime getHireDay() {
return hireDay;
}
public void setHireDay(LocalDateTime hireDay) {
this.hireDay = hireDay;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;//优化
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return Objects.equals(name, employee.name) &&
Objects.equals(salary, employee.salary) &&
Objects.equals(hireDay, employee.hireDay);
}
@Override
public int hashCode() {
return Objects.hash(name, salary, hireDay);
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + ''' +
", salary=" + salary +
", hireDay=" + hireDay +
'}';
}
}
package com.wx1.test4;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* User: Mr.Wang
* Date: 2019/10/27
*/
public class Manager extends Employee {
private Double bonus;
public static final String NO_STR = "str";
public Manager(String name, Double salary, LocalDateTime hireDay) {
super(name, salary, hireDay);
bonus = 0d;
}
public Double getBonus() {
return super.getSalary() + this.getBonus();
}
public void setBonus(Double bonus) {
this.bonus = bonus;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
Manager manager = (Manager) o;
return Objects.equals(bonus, manager.bonus);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), bonus);
}
}
ok,我要查看这两个类的结构可以获得这个类的构造器,方法,域,以及他们的修饰符,参数类型,返回值类型等等。
package com.wx1.test4;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* User: Mr.Wang
* Date: 2019/10/27
*/
public class Test1 {
public static void main(String[] args) {
//检查类的结构
try {
Class<Employee> employeeClass = Employee.class;
Class<?> aClass = Class.forName("com.wx1.test4.Manager");
//不包括超类
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
Method[] declaredMethods = aClass.getDeclaredMethods();
Field[] declaredFields = aClass.getDeclaredFields();
//拿到public域包括超类,拿到方法包括超类,拿到本类的构造器
Constructor<?>[] constructors = aClass.getConstructors();
Field[] fields = aClass.getFields();
Method[] methods = aClass.getMethods();
//拿到构造器的修饰符
List<String> collect = Arrays.stream(declaredConstructors)
.map((e) -> Modifier.toString(e.getModifiers()))
.collect(Collectors.toList());
//拿到构造器的名字,构造器的参数类型
Map<String, List<String>> collect1 = Stream.of(declaredConstructors)
.collect(Collectors.toMap(e -> e.getName(), e -> Stream.of(e.getParameterTypes()).map(v -> v.getName()).collect(Collectors.toList())));
//拿到方法的修饰符
List<String> collect2 = Arrays.stream(methods)
.map(e -> Modifier.toString(e.getModifiers()))
.collect(Collectors.toList());
//拿到方法的返回值类型
List<? extends Class<?>> collect3 = Arrays.stream(methods)
.map(e -> e.getReturnType())
.collect(Collectors.toList());
//拿到方法的参数类型,按照子类和超类来分组
Map<? extends Class<?>, List<Method>> listMap = Arrays.stream(methods)
.collect(Collectors.groupingBy(e -> e.getDeclaringClass()));
for (Method method : methods) {
Class<?> declaringClass = method.getDeclaringClass();
Class<?> returnType = method.getReturnType();
String name = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
String name1 = parameterType.getName();
}
}
//拿到域的修饰符
List<String> collect4 = Stream.of(fields)
.map(e -> Modifier.toString(e.getModifiers()))
.collect(Collectors.toList());
//拿到域的类型
List<? extends Class<?>> collect5 = Stream.of(fields)
.map(e -> e.getType())
.collect(Collectors.toList());
} catch (Exception e) {
e.printStackTrace();
}
}
}
7.在运行时使用反射分析对象
比如在运行时拿的到对象属性的值,设置对象属性的值,判断访问修饰符,这里需要注意一个问题就是java反射机制默认行为受限于java的访问控制。
例如在运行时拿到employee对象的属性值:
Employee employee=new Employee("MrWang",50000d,LocalDateTime.now());
Class<? extends Employee> aClass1 = employee.getClass();
Field name = aClass1.getDeclaredField("name");
name.setAccessible(true);
Object o = name.get(employee);
可以将所有的域设置为可访问,那么也就可以编写一个通用的toString()方法。
8.使用反射可以编写泛型的数组
在反射包下有一个Array对象,有一个newInstance方法可以创建新的数组,下面我们来编写一个扩展数组的方法,int[]可以转换为Object,所以参数的签名为Object.
public static Object copyOf(Object o, int newLength) {
Class<?> aClass = o.getClass();
if (!aClass.isArray()) {
return null;
}
Class<?> componentType = aClass.getComponentType();
int length = Array.getLength(o);
Object newInstance = Array.newInstance(componentType, newLength);
System.arraycopy(o, 0, newInstance, 0,
Math.min(length, newLength));
return newInstance;
}
测试:
String[] a = {"w", "x", "c"};
String[] strings = (String[]) Test1.copyOf(a, 10);
int length = strings.length;
9.调用任意方法
Method类中有一个invoke方法,它允许调用包装在当前Method对象中的方法。静态方法第一个参数可以设置为null
更多Class API方法:https://www.jianshu.com/p/9be58ee20dee
最后
以上就是含糊画板为你收集整理的java基础--14(反射)的全部内容,希望文章能够帮你解决java基础--14(反射)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复