反射是指对于任何一个Class类,在运行时都可以直接得到这个类的全部成分
这种运行时动态获取信息以及动态调用类中成分的能力称为java的反射机制
获取字节码文件
public static void main(String[] args) throws Exception {
Class class1=Class.forName("reflect.Student");
System.out.println(class1);
}
Class class2=Student.class;
System.out.println(class2);
Student student=new Student();
Class class3=student.getClass();
System.out.println(class3);
获取全部的构造器,但是只能获取public修饰的
@Test
public void getConstructors(){
//获取反射对象
Class c = Student.class;
//提取所有的构造器对象
Constructor []constructors= c.getConstructors();
//遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName()+"===>"+constructor.getParameterCount());
}
}
获取全部的构造器,无论权限
@Test
public void getDeclaredConstructor(){
Class c = Student.class;
//提取所有的构造器对象
Constructor []constructors= c.getDeclaredConstructors();
//遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName()+"===>"+constructor.getParameterCount());
}
}
获取指定的构造器,只能获取public
@Test
public void getConstructor() throws Exception {
Class c = Student.class;
Constructor constructor=c.getConstructor();
System.out.println(constructor.getName()+"===>"+constructor.getParameterCount());
}
获取指定构造器,无论权限
@Test
public void getDeclaredConstructor() throws Exception {
Class c = Student.class;
Constructor constructor1= c.getDeclaredConstructor();
Constructor constructor2= c.getDeclaredConstructor(String.class,int.class);
System.out.println(constructor1.getName()+"===>"+constructor1.getParameterCount());
System.out.println(constructor2.getName()+"===>"+constructor2.getParameterCount());
}
@Test
public void getback() throws Exception {
Class c = Student.class;
Constructor constructor1= c.getDeclaredConstructor();
Constructor constructor2= c.getDeclaredConstructor(String.class,int.class);
//遇到私有的反射器,可以暴力反射
constructor1.setAccessible(true);
Student student1=(Student) constructor1.newInstance();
Student student2=(Student) constructor2.newInstance("张三",10086);
System.out.println(student1);
System.out.println(student2);
}
反射可以破坏封装性,运行私密的
获取所有的对象,无论权限
@Test
public void getDeclardeFields(){
Class c=Student.class;
Field[] fields= c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName()+"===>"+field.getType());
}
}
获取单个对象,无论权限
@Test
public void getDeclardeField() throws Exception {
Class c=Student.class;
Field field1=c.getDeclaredField("age");
System.out.println(field1.getName()+"===>"+field1.getType());
Field field2=c.getDeclaredField("name");
System.out.println(field2.getName()+"===>"+field2.getType());
}
给成员变量赋值
@Test
public void getback() throws Exception {
Class c=Student.class;
Field fieldAge= c.getDeclaredField("age");
fieldAge.setAccessible(true);
Student s=new Student();
fieldAge.set(s,18);
System.out.println(s);
int age=(int)fieldAge.get(s);
System.out.println(age);
}
同样的因为成员变量为私有,需要用到暴力反射
获取所有的方法,无论权限
@Test
public void getDeclaredMethods(){
Class c=Student.class;
Method[] methods=c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName()+"返回值类型"+method.getReturnType()+"参数数量"+method.getParameterCount());
}
}
获取指定方法,无论权限
@Test
public void getDeclaredMethod() throws Exception {
Class c=Student.class;
Method method1=c.getDeclaredMethod("run");
System.out.println(method1.getName()+"返回值类型"+method1.getReturnType()+"参数数量"+method1.getParameterCount());
Method method2=c.getDeclaredMethod("run",String.class);
System.out.println(method2.getName()+"返回值类型"+method2.getReturnType()+"参数数量"+method2.getParameterCount());
}
获取方法并使用
@Test
public void getback() throws Exception {
Class c=Student.class;
Method method1=c.getDeclaredMethod("run");
Method method2=c.getDeclaredMethod("run",String.class);
method1.setAccessible(true);
method2.setAccessible(true);
Student s=new Student();
Object result1=method1.invoke(s);
System.out.println(result1);
Object result2=method2.invoke(s,"李四");
System.out.println(result2);
}
public static void main(String[] args) {
ArrayList<String> list1=new ArrayList<>();
ArrayList<Integer>list2=new ArrayList<>();
System.out.println(list1.getClass());
System.out.println(list2.getClass());
System.out.println(list1.getClass()==list2.getClass());
}

首先们可以通过上述的一个小例子看到,在无论是何种类型的ArrayList集合,其类型都是相同的,这就意味着,当代码编译成Class文件进入运行阶段之后,泛型会自动擦除,而反射是恰恰是针对运行阶段的技术,很显然我们可以绕过泛型的约束
ArrayList<Integer>list3=new ArrayList<>();
list3.add(1);
list3.add(114514);
list3.add(1919810);
Class c=list3.getClass();
Method method=c.getDeclaredMethod("add", Object.class);
method.invoke(list3,"浩二");
System.out.println(list3);

其实还可以通过地址直接绕过泛型的约束
public static void main(String[] args) {
ArrayList<Integer> list3=new ArrayList<>();
list3.add(1);
list3.add(114514);
list3.add(1919810);
ArrayList list4=list3;
list4.add("浩二");
list4.add(false);
System.out.println(list3);
}

这么看来泛型的约束好像和马奇诺防线一样,谁都能绕
先创建两个要读取的类
Student类
public class Student {
private String name;
private char sex;
private int age;
private String className;
private String hobby;
public Student() {
}
public Student(String name, char sex, int age, String className, String hobby) {
this.name = name;
this.sex = sex;
this.age = age;
this.className = className;
this.hobby = hobby;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
", className='" + className + '\'' +
", hobby='" + hobby + '\'' +
'}';
}
}
Teacher类
public class Teacher {
private String name;
private char sex;
private double salary;
public Teacher(){
}
public Teacher(String name, char sex, double salary) {
this.name = name;
this.sex = sex;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", sex=" + sex +
", salary=" + salary +
'}';
}
}
创建一个工具类用于得到类的内容,并打印
public class Utils {
public static void save(Object obj) {
try (PrintStream ps=new PrintStream(new FileOutputStream("junit_class/src/data.txt",true)))
{
Class c = obj.getClass();
//getSimpleName获取当前类名,getName获取包名加类名
ps.println("============="+c.getSimpleName()+"================");
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
//获取成员变量的值,采用拼字符串的方式,防止类型强转出错
field.setAccessible(true);
String value = field.get(obj) + "";
ps.println(name +"="+value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
最后是主程序
public class reflectDemo {
public static void main(String[] args) {
Student student=new Student();
student.setName("浩二");
student.setAge(114514);
student.setSex('难');
student.setClassName("下北泽高级中学");
student.setHobby("蕨");
Utils.save(student);
Teacher teacher=new Teacher();
teacher.setName("静可爱");
teacher.setSex('女');
teacher.setSalary(100000);
Utils.save(teacher);
}
}
看看文件里的内容

完美结束