java反射

java 1.2反射

java 基础四大接口

Comparable 用于对象比较的接口;

Runnable 用于对象线程话的接口;

Serializable 用于对象序列化的接口;

Clonable 用于对象克隆的接口;

通过反射创建对象

//创建A对象,通过newInstance方法
Object obj6 = Class.forName("A").newInstance();
Method m = Class,forName("A").getMethod("hello");
m.invoke(obj6);
//
Constructor<A> constructor = A.class.getConstructor();
A obj8 = constructor.newInstance();
obj8.hello();

类关键字

Class:类型标识

成员变量、方法、构造函数、修饰符、包、父类、父接口...

image-20210912162437241

// 类成员变量Filed
Class A{
    public int age;
    private String name;
    
    public A(int age,String name){
        this.age = age;
        this.name = name;
    }
}
//反射
A obj = new A(2,"Tom");
Class c = obj.getClass();
//获取本类及父类所有的public字段
Field[] fs = c.getFields();

//获取本类所有声明的字段
Field[] fs2 = c.getDeclaredFields();
for(Field f : fs2){
    //临时将私有方法转化为公有
    f.setAccessible(true);
    System.out.println(f.getName() + ":" + f.get(obj));
}
//成员方法Method
class B{
    public void f1(){
        out.printl("B.f1()...");
    }
    
    private String f2(String s){
        out.println("B.f2()...");
        return s;
    }
}
//反射
B obj = new B();
Class c = obj.getClass();
//获取public方法 包括父类和父接口
Method[] ms = c.getMethods();
for(Method m : ms){
    if("f1".equals(m.getName())){
        m.invoke(obj,null);
    }
}
//获得该类的所有方法
Method[] ms2 = c.getDeculareMethods();
for(Method m : ms2){
    if("f2".equals(m.getName())){
        m.setAccessible(true);
        String result = (String)m.invoke(obj,"abc");
    }
}
//构造函数 Constructor
class D{
    private int num;
    
    public D(){
        this.num = 10;
    }
    public D(int num){
        this.num = num;
    }
    
    public void printNum(){
        System.out.println(this.num);
    }
}
//反射
D d = new D();
Class c = d.getClass();

Constructor[] cons = c.getConstructor();
for(Constructor con : cons){
    if(con.getParameterCount() > 0){
        // 有参构造函数
        D obj = (D) con.newInstance(100);
        obj.printNum();
    }else{
     	// 无参构造函数
        D obj = (D) con.newInstance();
        obj.printNum();
    }
}
//父类、父接口
class Father{}

class Son extends Father implements Cloneable,Comparable{
    protected Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
    public int compareTo(Object o){
        return o;
    }
}
//反射
Son son = new Son();
Class c = son.getClass();

//获取父类(Father)
Class father = c.getSuperclass();
System.out.println(father.getName());

//获取父接口
Class[] inters = c.getInterfaces();
for(Class inter : inters){
    System.out.println(inter.getName());
}

反射应用场景

  • 数据库连接

    // -Connection,连接到各个不同数据库
    try{
        //通知类加载器加载此类的class文件
        class.forName("com.mysql.jdbc.Driver");
    }catch(ClassNotFoundException e1){
        e1.printStackTrace();
        return;
    }
    //构建按java 和数据库之间的桥梁:URL,用户名,密码
    conn = DriverManager.getConnection(url,"root","123456");
    //DriverManager将会挑选加载合适的驱动类,并采用getConnection方法连接
    
  • 数组扩充

    给定一个数组(任意类型),将其长度扩大一倍

    java的数组一旦创建,其长度是不再更改的

    新建的一个大数组(相同类型),然后将旧数组的内容拷贝过去

    public static Object goodCopy(Object oldArray, int newLength){
        //Array类型
        Class c = oldArray.getClass();
        
        //获取数组中的单个元素类型
        Class componentType = c.getComponentType();
        
        //旧数组长度
        int oldLength= Array.getLength(oldArray);
        //新数组:创建新数组,数组内元素类型约束为componentType类型,新数组长度为newLength
        object newArray = Array.newInstance(componentType,newLength);
        //拷贝旧数据
        System.arraycopy(oldArray,0,newArray,0,oldlength);
        return newArray;
    }
    int[] a = {1,2,3,4,5};
    a = (int[]) goodcopy(a,10);
    for(int i : a){
        System.out.pringln(i);
        //1 2 3 4 5 0 0 0 0 0
    }
    
  • 动态执行方法

    给定类名、方法名、即可执行

    加上定时器,即可做定时任务执行

    class Worker{
        public static void hello(){
            System.out.println("Hello java!");
        }
    }
    
    class MyTest extends TimerTask{
        public void run(){
            try{
                Method m = Class.forName("Worker").getClass().getMethod("hello");
                m.invoke(null);// 静态方法可以不用new对象
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    //test
    Timer timer = new Timer();
    
    Calendar now = Calendar.getInstance();
    now.set(Calendar.SECOND,now.get(Calendar.SECOND)+1);
    Date runDate = now.getTime();
    
    MyTask task2 = new MyTask();
    timer.scheduleAtFixeRate(task2,runDate,3000);
    
  • Tomcat的Servlet创建

    <!-- web.xml-->
    <!-- servlet definition-->
    <servlet>
        <servlet-name>Init</servlet-name>
        <servket-class>service.Init</servket-class>
    </servlet>
    
    public Object newInstance(final String classNmae,final ClassLoader classloader) throws IllegalAccessException,NamingException,InvocationTargetException,InstantiationException,ClassNotFoundException,IllegalArgumentExcption,NoSuchMethodException,SecurityException{
        Class<?> clazz = classLoader.loadClass(className);
        return newInstance(clazz.getConstructor().newInstance(),clazz);
    }
    
    备注:
    Class.forName(className)方法,内部实际调用的方法是  Class.forName(className,true,classloader);
    
    第2个boolean参数表示类是否需要初始化,  Class.forName(className)默认是需要初始化。一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。
    
        
    
    ClassLoader.loadClass(className)方法,内部实际调用的方法是  ClassLoader.loadClass(className,false);
    
    第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以,不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行
    
  • Mybatis:OR/M (Object-Relation Mapping)

    数据库表和java的POJO/DAO类对应关系

    //mybatis对java反射进行的一个封装,所有与反射相关的操作,均靠此类执行
    public class Reflector{
        private final Class<?> type;
        private final String[] readablePropertyNames;
        private final String[] writeableProperNames;
        private final Map<String, Invoker> setMethods = new HashMap<>();
        private final Map<String, Invoker> getMethods = new HashMap<>();
        private final Map<String, Class<?>> setTypes = new HashMap<>();
        private final Map<String, Class<?>> getTypes = new HashMap<>();
        private Constructor<?> defaultConstructor;
        
        private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
        
        public Reflector(Class<?> clazz){
            type = clazz;
            addDefaultConstructor(clazz);
            addGetMethods(clazz);
            addSetMethods(clazz);
            addFields(clazz);
            redablePropertyNames = getMethods.keySet().toArray(new String[0]);
            writeableProperNames = setMethods.keySet().toArray(new String[0]);
        }
    }
    
posted @ 2021-10-19 10:08  绝不是木头  阅读(53)  评论(0)    收藏  举报