1、反射机制
在程序运行状态中,对于任意一个类或对象,都能够获取到这个类的所有属性和方法(包括私有属性和方法),这种动态获取信息以及动态调用对象方法的功能就称为反射机制。通过反射,类对我们是完全透明的,可以获取类中的任何东西。
2、获取Class对象的三种方式
我们知道,Java是完全面向对象的,所以在Java的世界里任何事物都可以理解为对象,类也不例外,下面是获取Class对象的三种方式。
package com.demo;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//Source源代码阶段 Class.forName("全限定名")(常用)
Class class1 = Class.forName("com.demo.Person");
System.out.println("class1 = " + class1);
//Class类对象阶段 类名.class
Class class2 = Person.class;
System.out.println("class2 = " + class2);
//Runtime运行时阶段 对象.getClass()
Person person = new Person();
Class class3 = person.getClass();
System.out.println("class3 = " + class3);
//对比获取的对象是否相同
System.out.println(class1==class2);
System.out.println(class2==class3);
}
}
class1 = class com.demo.Person
class2 = class com.demo.Person
class3 = class com.demo.Person
true
true
通过运行结果可证明,同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。
3、Class对象的功能
测试类
package com.demo;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
//获取Class对象
Class studentClass = Class.forName("com.demo.Student");
//获取单个public修饰的无参构造方法
Constructor constructor1 = studentClass.getConstructor();
System.out.println("constructor1 = " + constructor1);
System.out.println();
//获取单个public修饰的有多个参数的构造方法
Constructor constructor2 = studentClass.getConstructor(String.class, String.class, int.class, int.class);
System.out.println("constructor2 = " + constructor2);
System.out.println();
//获取单个构造方法(不论修饰符)
Constructor constructor3 = studentClass.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("constructor3 = " + constructor3);
System.out.println();
//获取所有public修饰的构造方法
Constructor[] constructors1 = studentClass.getConstructors();
for (Constructor constructor : constructors1) {
System.out.println(constructor);
}
System.out.println();
//获取所有的构造方法(不论修饰符)
Constructor[] constructors2 = studentClass.getDeclaredConstructors();
for (Constructor constructor : constructors2) {
System.out.println(constructor);
}
}
}
Person类
package com.demo;
//@Setter 替代Setter方法
@Setter
//@Getter 替代Getter方法
@Getter
//替代toString方法
@ToString
public class Person {
public String name;
protected int age;
char sex;
private double height;
//无参的公开构造
public Person() {
}
//有多个参数的公开的有参构造
public Person(String name, int age, char sex, double height) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
}
//有一个参数的受保护的有参构造
protected Person(String name) {
this.name = name;
}
//有两个参数的default的有参构造
Person(String name, int age) {
this.name = name;
this.age = age;
}
//有多个参数的私有的有参构造
private Person(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Student类
package com.demo;
//@Setter 替代Setter方法
@Setter
//@Getter 替代Getter方法
@Getter
//替代toString方法
@ToString
public class Student extends Person {
public String grade;
protected String classname;
int studentID;
private int score;
//无参的公开构造
public Student() {
}
//有多个参数的公开的有参构造
public Student(String grade,String classname, int studentID,int score) {
this.grade = grade;
this.classname=classname;
this.studentID = studentID;
this.score = score;
}
//有一个参数的受保护的有参构造
protected Student(String grade) {
this.grade = grade;
}
//有两个参数的default的有参构造
Student(String grade, int studentID) {
this.grade = grade;
this.studentID = studentID;
}
//有多个参数的私有的有参构造
private Student(String grade, int studentID,int score) {
this.grade = grade;
this.studentID = studentID;
this.score = score;
}
}
运行结果
constructor1 = public com.demo.Student()
constructor2 = public com.demo.Student(java.lang.String,java.lang.String,int,int)
constructor3 = private com.demo.Student(java.lang.String,int,int)
public com.demo.Student(java.lang.String,java.lang.String,int,int)
public com.demo.Student()
private com.demo.Student(java.lang.String,int,int)
com.demo.Student(java.lang.String,int)
protected com.demo.Student(java.lang.String)
public com.demo.Student(java.lang.String,java.lang.String,int,int)
public com.demo.Student()
package com.demo;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws Exception {
//获取Class对象
Class studentClass = Class.forName("com.demo.Student");
//获取单个public修饰的无参构造方法
Constructor constructor1 = studentClass.getConstructor();
//调用public修饰的无参构造方法
Object object1=constructor1.newInstance();
System.out.println(object1+"\n"+object1.getClass()+"\n");
//获取单个构造方法(不论修饰符)
Constructor constructor2 = studentClass.getDeclaredConstructor(String.class);
//调用protected修饰的有一个参数的有参构造
Object object2=constructor2.newInstance("九年级");
System.out.println(object2+"\n"+object2.getClass()+"\n");
//获取单个构造方法(不论修饰符)
Constructor constructor3 = studentClass.getDeclaredConstructor(String.class, int.class, int.class);
/*
调用private修饰的有多个参数的有参构造
setAccessible(true) 暴力访问(忽略访问修饰符)
只有private修饰的才需要暴力访问
*/
constructor3.setAccessible(true);
Object object3=constructor3.newInstance("八年级",202101,96);
System.out.println(object3+"\n"+object3.getClass());
}
}
Student{grade='null', classname='null', studentID=0, score=0}
class com.demo.Student
Student{grade='九年级', classname='null', studentID=0, score=0}
class com.demo.Student
Student{grade='八年级', classname='null', studentID=202101, score=96}
class com.demo.Student
测试类
package com.demo;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
//获取Class对象
Class studentClass = Class.forName("com.demo.Student");
/*
获取单个public修饰的成员变量(包括从父类中继承的成员变量)
注意:Student类中未定义成员变量name
*/
Field field1 = studentClass.getField("name");
System.out.println("field1 = " + field1);
System.out.println();
//获取单个成员变量(不论修饰符)
Field field3 = studentClass.getDeclaredField("score");
System.out.println("field3 = " + field3);
System.out.println();
//获取所有public修饰的成员变量(包括从父类中继承的成员变量)
Field[] fields1 = studentClass.getFields();
for (Field field : fields1) {
System.out.println(field);
}
System.out.println();
//获取所有的成员变量(不论修饰符,不包括从父类中继承的成员变量)
Field[] fields2 = studentClass.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field);
}
}
}
Person类
package com.demo;
//替代toString()方法
@ToString
public class Person {
public String name;
protected int age;
char sex;
private double height;
//无参的公开构造
public Person() {
}
//有多个参数的公开的有参构造
public Person(String name, int age, char sex, double height) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
}
//有一个参数的受保护的有参构造
protected Person(String name) {
this.name = name;
}
//有两个参数的default的有参构造
Person(String name, int age) {
this.name = name;
this.age = age;
}
//有多个参数的私有的有参构造
private Person(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Student类
package com.demo;
//替代toString()方法
@ToString
public class Student extends Person {
public String grade;
protected String classname;
int studentID;
private int score;
//无参的公开构造
public Student() {
}
//有多个参数的公开的有参构造
public Student(String grade,String classname, int studentID,int score) {
this.grade = grade;
this.classname=classname;
this.studentID = studentID;
this.score = score;
}
//有一个参数的受保护的有参构造
protected Student(String grade) {
this.grade = grade;
}
//有两个参数的default的有参构造
Student(String grade, int studentID) {
this.grade = grade;
this.studentID = studentID;
}
//有多个参数的私有的有参构造
private Student(String grade, int studentID,int score) {
this.grade = grade;
this.studentID = studentID;
this.score = score;
}
}
运行结果
field1 = public java.lang.String com.demo.Person.name
field3 = private int com.demo.Student.score
public java.lang.String com.demo.Student.grade
public java.lang.String com.demo.Person.name
public java.lang.String com.demo.Student.grade
protected java.lang.String com.demo.Student.classname
int com.demo.Student.studentID
private int com.demo.Student.score
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
//获取Class对象
Class studentClass = Class.forName("com.demo.Student");
//获取构造方法
Constructor constructor=studentClass.getDeclaredConstructor(String.class,int.class,int.class);
//暴力访问
constructor.setAccessible(true);
Object object1=constructor.newInstance("八年级",202102,94);
System.out.println("object1 = " + object1);
//获取public修饰的成员变量
Field grade=studentClass.getField("grade");
//调用public修饰的成员变量
grade.set(object1,"九年级");
//获取非public修饰的成员变量
Field score= studentClass.getDeclaredField("score");
//暴力访问(忽略访问修饰符)
score.setAccessible(true);
score.set(object1,90);
System.out.println("object1 = " + object1);
}
}
object1 = Student(grade=八年级, classname=null, studentID=202102, score=94)
object1 = Student(grade=九年级, classname=null, studentID=202102, score=90)
测试类
package com.demo;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
//获取Class对象
Class studentClass = Class.forName("com.demo.Student");
/*
获取单个public修饰的成员方法(包括从父类中继承的成员方法)
注意:Student类中未重写eat方法
*/
Method method1=studentClass.getMethod("eat");
System.out.println("method1= " + method1);
System.out.println();
//获取单个成员方法(不论修饰符)
Method method2=studentClass.getDeclaredMethod("fun4");
System.out.println("method2 = " + method2);
System.out.println();
/*
getMethods() 获取所有public修饰的成员方法(包括从父类中继承的方法,若该方法被重写,则只返回子类中重写的方法)
注意:Student类中未重写eat方法,Object类是所有类的父类
*/
Method[] methods1=studentClass.getMethods();
for(Method method:methods1){
System.out.println(method);
}
System.out.println();
//getDeclaredMethods() 获取所有的成员方法(不论修饰符,不包括从父类中继承的方法)
Method[] methods2=studentClass.getDeclaredMethods();
for(Method method:methods2){
System.out.println(method);
}
}
}
Person类
package com.demo;
//替代toString方法
@ToString
public class Person {
public void play(){
System.out.println("玩耍");
}
public void eat() {
System.out.println("吃饭");
}
protected void sleep() {
System.out.println("睡觉");
}
void run() {
System.out.println("跑步");
}
private void study() {
System.out.println("学习");
}
}
Student类
package com.demo;
//替代toString方法
@ToString
public class Student extends Person {
@Override
public void play(){
System.out.println("学生在玩耍");
}
public void fun1(int num) {
System.out.println("fun1"+" "+num);
}
protected void fun2(){
System.out.println("fun2");
}
void fun3() {
System.out.println("fun3");
}
private void fun4(){
System.out.println("fun4");
}
}
运行结果
method1= public void com.demo.Person.eat()
method2 = private void com.demo.Student.fun4()
public java.lang.String com.demo.Student.toString()
public void com.demo.Student.fun1(int)
public void com.demo.Student.play()
public void com.demo.Person.eat()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public java.lang.String com.demo.Student.toString()
public void com.demo.Student.fun1(int)
public void com.demo.Student.play()
void com.demo.Student.fun3()
protected void com.demo.Student.fun2()
private void com.demo.Student.fun4()
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
//获取Class对象
Class studentClass = Class.forName("com.demo.Student");
//获取构造方法
Constructor constructor= studentClass.getConstructor();
Object object=constructor.newInstance();
//获取public修饰的有参数的成员方法
Method method1=studentClass.getMethod("fun1", int.class);
/*
调用public修饰的成员方法,需要两个参数,一个是要调用的对象,一个是实参
public void com.demo.Student.fun1(int)
*/
method1.invoke(object,18);
//获取非public修饰的成员方法
Method method2=studentClass.getDeclaredMethod("fun4");
//暴力访问(忽略访问修饰符)
method2.setAccessible(true);
method2.invoke(object);
}
}
fun1 18
fun4
测试类
package com.demo;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
//获取Class对象
Class personClass = Class.forName("com.demo.Person");
Method method=personClass.getMethod("main",(String[].class));
method.invoke(null, (Object) new String[]{});
}
}
Person类
package com.demo;
public class Person {
public static void main(String[] args) {
System.out.println("Person类的main方法");
}
}
运行结果
Person类的main方法
测试类
package com.demo;
public class Test {
public static void main(String[] args) throws Exception {
Person person = new Person();
//获取Class对象
Class personClass = person.getClass();
System.out.println(personClass.getName());
}
}
Person类
package com.demo;
public class Person {
}
运行结果
com.demo.Person