- 一.反射机制
- Class类
package hellojava.day14; public class Test { public static void main(String[] args) {//实例化class类对象的四种方法 Person p=new Person(); Class clazz=p.getClass();// clazz对象中就包含对象P所属的Person类的所有信息 Class c0=Person.class;//通过类名,class创建指定类的class实例 Class c1=p.getClass();//通过一个类的实例对象的getClass()方法,获得对应实例对象的类的class实例 try { Class C2=Class.forName("day14.Person");//通过 Class的静态方法forName("day14.Person");方法获取 // 一个类的Class实例 //forName("day14.Person")方法中的参数是呢要获取的class实例的全路径(包名.类名) } catch (ClassNotFoundException e) { e.printStackTrace(); } } } - 通过反射调用类的完整结构(Field Method Constructor Superclass Interface Annotation) package hellojava.day14;public class Person { } public class Student extends Person implements Move,Study{ String school; public void showInfo(){ System.out.println("学校是:"+this.school); } @Override public void moveType() { System.out.println("骑自行车上学"); } @Override public void studyInfo() { System.out.println("学习的是大学的知识"); } }
package hellojava.day14;
public interface Move {
void moveType();
}
package hellojava.day14;
public interface Study {
void studyInfo();
}
package hellojava.day14;
public class Person {
String name;
int age;
}
public class Test1 {
public static void main(String[] args) {
try {//通过包名.类名的字符串,调用calss.forname方法获取指定类的class实例
Class clazz=Class.forName("hellojava.day14.Student");
Class superClazz = clazz.getSuperclass();//获取父类
System.out.println("父类:"+superClazz.getName());
Class[] interfaces= clazz.getInterfaces();//获取当前所有接口
for (Class c:interfaces){
System.out.println("接口:"+c.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
获取构造器
import java.lang.reflect.Constructor;
public class Test1 {
public static void main(String[] args) {
try {//通过包名.类名的字符串,调用calss.forname方法获取指定类的class实例
Class clazz=Class.forName("hellojava.day14.Student");
Class superClazz = clazz.getSuperclass();//获取父类
System.out.println("父类:"+superClazz.getName());
Class[] interfaces= clazz.getInterfaces();//获取当前所有接口
for (Class c:interfaces){
System.out.println("接口:"+c.getName());
}
Constructor[] cons= clazz.getConstructors();//获取到类公有的构造方法
for (Constructor c:cons){
System.out.println("构造方法名称:"+c.getName());//获取方法名称
//getModifiers()获取方法修饰符返回数组1代表public
System.out.println("构造方法名称:"+c.getName()+"的修饰符是:"+c.getModifiers());//获取方法修饰符
Class[] paramClazz =c.getParameterTypes();
for (Class pc:paramClazz){
System.out.println("构造方法名称:"+c.getName()+"的参数类型是:"+pc.getName());
}
}
Constructor[] cons1 =clazz.getDeclaredConstructors();//获取所有类的构造方法
for (Constructor c:cons1){
System.out.println("------------------------------");
System.out.println("构造方法名称:"+c.getName());//获取方法名称
//getModifiers()获取方法修饰符返回数组1代表public,返回数字2代表private
System.out.println("构造方法名称:"+c.getName()+"的修饰符是:"+c.getModifiers());
Class[] paramClazz =c.getParameterTypes();//获取构造方法的参数类型,有几个参数就有几个
for (Class pc:paramClazz){
System.out.println("构造方法名称:"+c.getName()+"的参数类型是:"+pc.getName());
}
System.out.println("------------------------------");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
用反射的构造方法来创建对象
//如果用反射的构造方法来创建对象
try {
Object obj= clazz.newInstance();//相当于调用 Student()类的无参公有的构造方法
Student stu=(Student)obj;
Constructor c=clazz.getConstructor(String.class);//指定获取有一个参数并且为String类型的公有构造
Student stu1= ( Student)c.newInstance("第一中学");//newInstance实例化对象
System.out.println(stu1.school);
//通过反射机制,可以强制的调用私有的构造方法
Constructor c1=clazz.getDeclaredConstructor(String.class,int.class);//指定获取有两个参数(String int)的构造方法
c1.setAccessible(true);//解除私有的封装,下面就可以对这个私有方法强制调用
Student stu2= ( Student)c1.newInstance("长得三",12);
System.out.println(stu2.school);
} catch (Exception e) {
e.printStackTrace();
}
Method[] ms=clazz.getMethods();//获取到类的所有公有的方法
//Method[] ms1=clazz.getDeclaredMethods();//获取到类的所有方法
for (Method m:ms){
System.out.println("方法名:"+m.getName());
System.out.println("返回值类型:"+m.getReturnType());
System.out.println("修饰符:"+m.getModifiers());
Class[]pcs= m.getParameterTypes();//获取方法的参数类型,是一个数组,方法有几个参数,数据就有几个元素
if (pcs!=null&&pcs.length>0){
for (Class pc:pcs){
System.out.println("参数类型:"+pc.getName());
}
}
System.out.println("=================================");
Field[] fs=clazz.getFields();//获取类公有的属性,包含父类
// Field[] fs=clazz.getDeclaredFields();//获取本类(不包含父类)所有的属性包含私有属性
for (Field f:fs){
System.out.println("修饰符"+f.getModifiers());
System.out.println("属性的类型"+f.getType());
System.out.println("属性的名称"+f.getName());
}
类所在的包
Package p=clazz.getPackage();//获取类所在的包 System.out.println(p.getName());
通过反射调用类中的指定方法
在上面代码Student类中加入如下代码
private void test(String name){
System.out.println("这个是test(String name)私有方法");
}
public String getSchool(){
return this.school;
}
public void setInfo(String name,String school){
this.name=name;
this.school=school;
System.out.println("这个是setInfo(String name,String school){方法");
}
public void setInfo(int age){
this.name=name;
this.school=school;
System.out.println("这个是setInfo(int age){方法");
}
在Test1类中写调用测试
//下面不论是反射调用setinfo还是test方法都是调用的obj的方法
// obj对象实际上就是student对象
Constructor con=clazz.getConstructor();//获取无参构造
Object obj=con.newInstance();//使用无参构造创建对象
Method m= clazz.getMethod("setInfo",String.class,String.class);
//得到名称setInfo的方法参数是String String
m.invoke(obj,"dg","大威德");//参数1.是实例化对象,2.是调用当前方法的实际参数
//如果想要调用一个私有的方法
Method m1=clazz.getDeclaredMethod("test",String.class);//获取方法名test参数为String类型的方法
m1.setAccessible(true);//解除私有封装,下面可以强制使用
m1.invoke(obj,"斩杀");
//调用一个重载方法
Method m2=clazz.getDeclaredMethod("setInfo",int.class);//setInfo的重载方法
m2.invoke(obj,1);
//有返回值的方法
Method m3=clazz.getMethod("getSchool");//sgetSchool的没有参数的方法
String school=(String) m3.invoke(obj);//调用有返回值但是无参数的方法
System.out.println(school);
} catch (Exception e) {
e.printStackTrace();
}
调用指定属性
//反射创建一个对象
Constructor con1=clazz.getConstructor();
Student stu1=(Student)con.newInstance();
Field f=clazz.getField("school");//获取名称为school属性
f.set(stu1,"第三中学");//对stu1对象的school属性设置值"第三中学"
String school1=(String) f.get(stu1);//获取stu1对象的school属性值
System.out.println(school1);
//如果是私有属性
Field f1=clazz.getDeclaredField("privateField");
f1.setAccessible(true);//解除私有的封装,以便强制调用
f1.set(stu1,"测试私有属性");
System.out.println(f1.get(stu1));
Java的动态代理
package hellojava.day14;
public interface ITestDemo {
void test1();
void test2();
}
public class TestDemoImpl implements ITestDemo {
public TestDemoImpl() {
super();
}
@Override
public void test1() {
System.out.println("执行test1");
}
@Override
public void test2() {
System.out.println("执行test2");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//动态代理类
public class ProxyDemo implements InvocationHandler {
Object obj;//被代理的对象
public ProxyDemo(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"方法开始执行");
Object result= method.invoke(this.obj,args);//执行的是指定代理对象指定的方法
System.out.println(method.getName()+"方法执行完毕");
return result;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test2 {
public static void main(String[] args) {
ITestDemo test=new TestDemoImpl();
// 注意 如果一个对象想要通过Proxy.newProxyInstance被代理,那么这个对象类一定要有相应的接口
// 就像本案例中TestDemo接口和实现类TestDemoImpl
test.test1();
test.test2();
System.out.println("============================================");
//需求在执行test1和test2方法时需要加入一些东西,在执行方法前打印test1或test2开始执行
//在执行方法后打印test1或test2执行完毕打印的方法要和当时调用方法保持一致
InvocationHandler handler=new ProxyDemo( test);
//Proxy.newProxyInstance()有三个参数,参数1是代理对象的类加载器参数二是被代理的对象的接口
//参数三是代理对象 返回值就是成功被代理的对象,返回的是object类型,需要根据当前的情况类型转换
ITestDemo t=(ITestDemo) Proxy.newProxyInstance(handler.getClass().getClassLoader(),test.getClass().getInterfaces(),handler);
t.test1();
System.out.println("============================================");
t.test2();
}
}
测试输出



