每天进步一点点
一、什么是反射
Java反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法和属性,这种动态获取的信息以及动态调用对象方法的功能称为反射。
Class类是一切反射根源
Class类表示什么???
很多的人—>可以定义为一个Person类(有姓名、性别、年龄)
很多的车—>可以定义一个Car类(有颜色、车牌,品牌)
很多个类—>可以定义一个Class类(有类名、属性、方法)
1.1 类对象
类加载的产物,封装了一个类中的所有属性(包名、类名、父类、接口、属性、方法、构造方法)
1.2 类的对象
基于某个类new出来的对象,也称实例对象
二、获取类对象的三种方法
- Object类中的getClass()方法
- 类.class
- 通过Class类的forName()方法
创建一个Person类,后面使用
package com.javase.reflection;
public class Person {
public int type;
private String name;//私有属性
int age;//默认属性
protected String sex;
public Person() {
System.out.println("无参构造方法被调用了!!!");
}//无参构造方法
//带三个参数的构造方法
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
System.out.println("带参构造方法被调用了!!!");
}
public void eat(){
//无参方法
System.out.println(this.name+"吃饭!!!");
}
public void eat(String food){
//一个参数方法
System.out.println(this.name+"吃"+food);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
//重写toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
2.1 Object类中的getClass()方法
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Person();
//第一种方法:Object中的getClass()方法
Class<? extends Person> aClass = person.getClass();
System.out.println(aClass);
}
}
2.2 类.class
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//第二中方法:类.class
Class<Person> bClass = Person.class;
System.out.println(bClass);
}
}
2.3 通过Class类的forName()方法
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//第三重方法:Class.forName()方法 (推荐使用第三种方式)
Class<?> cClass = Class.forName("com.javase.reflection.Person");
System.out.println(cClass);
}
}
三种方法的结果
三、使用反射进行类的实例化操作
3.1 调用无参构造方法进行实例化
public Constructor<T> getConstructor()
获取类的无参构造方法public T newInstance()
创建对象实例
public class TestCode01 {
public static void main(String[] args) throws Exception {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
//使用newInstance()方法创建实例,调用的是无参构造方法
Person p1 = (Person) aClass.newInstance();
//获取无参构造方法
Constructor<?> con = aClass.getConstructor();
Person p2 = (Person)con.newInstance();
}
}
3.2 调用有参构造方法进程实例化
public Constructor<T> getConstructor(类<?>... parameterTypes)
获取返回一个Constructor对象,该对象反映Constructor对象表示的类的指定的公共类函数。
public class TestCode01 {
public static void main(String[] args) throws Exception {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
Constructor<?> con = aClass.getConstructor(String.class, int.class, String.class);
Person p = (Person)con.newInstance("张三", 20, "男");
}
}
四、反射的常用操作
4.1 使用反射获取类名、包名、父类、接口
public String getName()
获取类的名字public Package getpackage()
获取类的包名public Class<? super T> getSuperclass()
获取类的父类public Class<?>[] getInterfaces()
获取类的接口
public class TestCode01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
//获取类的名字
String name = aClass.getName();
System.out.println(name);
//获取类的包名
Package aPackage = aClass.getPackage();
System.out.println(aPackage.toString());
//获取类的父类
Class<?> superclass = aClass.getSuperclass();
System.out.println(superclass.toString());//Object是所有类的父类
//获取类的接口
Class<?>[] interfaces = aClass.getInterfaces();//一个类可以继承多个接口,返回的是一个数组
System.out.println(interfaces.toString());
}
}
4.2 使用反射获取类的属性
getFields()
获取运行时类和父类中被public修饰的属性getDeclaredFields()
获取运行中的所有属性getField(String name)
,getDeclarreField(String name)
获取指定属性属性.getType()
获取属性的数据类型属性.getModifiers()
获取属性的修饰符属性.set(Object obj,Object value)
给属性赋值
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestCode02 {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.javase.reflection.Person");
//获取运行时类和父类中被public修饰的属性
Field[] fields = aClass.getFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("--------------------");
//获取运行中的所有属性
Field[] declaredFields = aClass.getDeclaredFields();
for(Field f : declaredFields){
System.out.println(f);
}
System.out.println("--------------------");
//获取指定属性
Field name = aClass.getDeclaredField("name");
System.out.println(name);
System.out.println("--------------------");
//获取属性的数据类型
Class<?> type = name.getType();
System.out.println(type);
System.out.println("--------------------");
//获取属性的修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
System.out.println(Modifier.toString(name.getModifiers()));
System.out.println("--------------------");
//给属性赋值
Field type1 = aClass.getField("type");
Person p =(Person) aClass.newInstance();
type1.set(p,22);
System.out.println(p.type);
}
}
4.3 使用反射获取类的构造方法
public Constructor<?>[] getConstructors()
获取类的构造方法
public class TestCode01 {
public static void main(String[] args) throws Exception {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
//获取类的构造方法
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor<?> con:constructors){
System.out.println(con.toString());
}
}
}
4.4 使用反射获取类中的方法并调用
getMethods()
获取public 的方法,包括从父类继承过来的方法getDeclaredMethods()
获取类中所有的方法,不包含继承方法
public class TestCode01 {
public static void main(String[] args) throws Exception {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
//获取类中public方法,包括父类继承过来的方法
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method.toString());
}
//获取类中所有的方法,包括private修饰的方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method.toString());
}
}
}
getMethod(String name, 类<?>...parameterTypers)
获取单个方法,参数为方法名,参数类型invoke(Object obj,Object... args)
在具有指定参数的方法对象上调用此方法对象表示的基础方法
public class TestCode01 {
public static void main(String[] args) throws Exception {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
//获取单个方法,无参方法并调用
Method eat1 = aClass.getMethod("eat");
Person p =(Person) aClass.newInstance();//创建对象
eat1.invoke(p);//==p.eat();
//获取一个带参的方法
Method eat2 = aClass.getMethod("eat", String.class);
eat2.invoke(p,"小龙虾!");
}
}
getDeclaredMethod()
可以获取类中的私有方法,但是私有方法不能直接调用,只能在类中调用,如果使用,就要设置它访问权限无效setAccessible(boolean b)
设置访问权限无效
public class TestCode01 {
public static void main(String[] args) throws Exception {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
Person p = (Person) aClass.newInstance();
//获取私有方法
Method privateMethod = aClass.getDeclaredMethod("privateMethod");
//设置访问权限无效
privateMethod.setAccessible(true);
//调用方法
privateMethod.invoke(p);
}
}
获取调用静态方法,使用invoke()方法不需要传入对象–>
invoke(null)
public class TestCode01 {
public static void main(String[] args) throws Exception {
//通过反射实例化对象
Class<?> aClass = Class.forName("com.javase.reflection.Person");
//获取私有方法
Method staticMethod = aClass.getDeclaredMethod("staticMethod");
//调用方法
staticMethod.invoke(null);//==p.staticMethod
}
}