Java的自学之旅14

  • 一.反射机制

 

  1. 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();
            }
        }
    }
  2. 通过反射调用类的完整结构(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();
    }
}
测试输出

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值