JAVA反射机制详解

反射机制有什么用

可以操作字节码文件

反射机制的相关类再哪个包下?

java.lang.reflect.*;

反射机制相关的类

java.lang.Class   代表字节码文件

java.lang.reflect.Method   代表字节码中的方法的字节码

java.lang.reflect.Constructor   代表字节码中的构造器的字节码

java.lang.reflect.Field   代表字节码中的属性的字节码

利用反射机制操作字节码文件

获取类的字节码

第一种方式:使用静态方法Class.forName(完整类名加包名)

Class c1 = Class.forName("java.lang.String");

Class.forName("java.lang.String");会导致类加载,即执行一次,String方法中的静态代码块也会执行一次,如果想一个类的静态方法执行一次,那么可以使用Class.forName()

第二种方式:使用Object类中的引用.getClass()方法

String s = "abc";
Class c = s.getClass();

第三种方式:java中的任意数据类型(包括基本数据类型)都有class属性

Class c = String.class;
Class c = int.class;

通过字节码文件来实例化对象

public class Test {
    public static void main(String[] args) {
        Class c = null;
        try {
            //通过反射机制获取字节码文件
            c = Class.forName("User");
            //newInstacnce()方法会调用User的无参构造方法来new一个User对象
            //必须保证User的无参构造方法存在!
            Object o = c.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }
}
class User{

}

注意:使用这种方法来初始化对象,更灵活!

举个例子

配置文件

//classinfo.Properties
className=com.sdut.wwg.User

User类

package com.sdut.wwg;

public class User {
    @Override
    public String toString() {
        return "User{}";
    }
}

Test类

import java.io.FileReader;
import java.util.Properties;

public class Test {
    public static void main(String[] args) throws Exception{
            //还可以这样获取绝对路径
            /*
            String path = Thread.currentThread().getContextClassLoader()
                .getResource("classinfo.Properities").getPath();
            
            还可以直接返回一个流
            InputStream r =Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("classinfo.Properities");
            */
            FileReader r = new FileReader("Demo/src/classinfo.Properities");
            Properties p = new Properties();
            p.load(r);
            r.close();
            String className = p.getProperty("className");
            //通过反射机制获取字节码文件
            Class c= Class.forName(className);
            //newInstacnce()方法会调用User的无参构造方法来new一个User对象
            //必须保证User的无参构造方法存在!
            Object o = c.newInstance();
            System.out.println(o);


    }
}

这样的优点在于当服务器运行的时候,可以直接修改配置文件,而不需要改代码情况下可以做到不同对象的实例化

反射属性

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;


public class Test {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("com.sdut.wwg.User");
        //获取完整类名
        System.out.println("完整类名为"+c.getName());
        System.out.println("简类名为"+c.getSimpleName());
        //获取User所有的公共属性
        Field[] fs = c.getFields();
        System.out.println("所有声明公有属性数量总计"+fs.length);

        //获取User所有的属性
        Field[] allFs = c.getDeclaredFields();
        System.out.println("所有声明属性数量总计"+allFs.length);
        System.out.println("属性名为:");
        for (int i = 0; i <allFs.length ; i++) {
            System.out.println(allFs[i].getName());
        }
        System.out.println("各属性类型为:");
        for (int i = 0; i <allFs.length ; i++) {
            //获取属性修饰符
            int s = allFs[i].getModifiers();
            System.out.println(s);
            //可以将这个代号数字转换为字符串
            String modifierString = Modifier.toString(s);
            System.out.println(modifierString);
            //获取属性的类型
            Class fieldType = allFs[i].getType();
            System.out.println(fieldType.getSimpleName());
        }
    }
}




通过反射机制来反编译一个类的属性(了解)

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;


public class Test {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("User");
        StringBuffer s= new StringBuffer();
        //获取类的修饰符列表和类名
        s.append(Modifier.toString(c.getModifiers())+" class "+c.getSimpleName()+"{\n");
        Field[] fields = c.getDeclaredFields();
        for(Field f:fields){
            s.append("\t"); 
            s.append(Modifier.toString(f.getModifiers())+" ");
            s.append(f.getType().getSimpleName()+" ");
            s.append(f.getName()+";\n");
        }
        s.append("}");
        System.out.println(s);
    }
}

输出结果为

通过访问机制来访问一个java对象的属性

import java.lang.reflect.Field;


public class Test {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("User");
        Object o = c.newInstance();
        //获取no属性
        Field noField = c.getDeclaredField("no");
        //给o对象的no属性赋值
        noField.set(o,1111);
        //读取属性的值
        System.out.println(noField.get(o));

        //可以访问私有属性吗??
        Field nameField = c.getDeclaredField("name");

        //需要打破封装.这样设置完之后,在外部也是可以访问私有属性的
        nameField.setAccessible(true);
        nameField.set(o,"jack");

        System.out.println(nameField.get(o));
    }
}

反射方法

public class Test {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("User");
        //获取所有的方法
        Method[] methods = c.getDeclaredMethods();
        //获取获取到的方法数量
        System.out.println(methods.length);
        for(Method m:methods){
            //输出方法的修饰符列表
            System.out.print(Modifier.toString(m.getModifiers())+" ");
            //输出方法的返回值类型
            System.out.print(m.getReturnType().getSimpleName()+" ");
            //输出方法的名字
            System.out.println(m.getName());
            //获取参数
            Class [] ctypes = m.getParameterTypes();
            for(Class clas: ctypes){
                //输出参数的类型
                System.out.println(clas.getSimpleName());
            }
        }
    }
}

反编译方法名和参数列表

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Test {
    public static void main(String[] args) throws Exception{

        StringBuffer s = new StringBuffer();
        Class c = Class.forName("java.lang.String");
        Method [] methods = c.getDeclaredMethods();
        for(Method m: methods){
            s.append('\t');
            s.append(Modifier.toString(m.getModifiers())+" "+m.getReturnType().getSimpleName()+" "+m.getName());
            s.append(" (");
            Class []classes = m.getParameterTypes();
            for(Class cls : classes){
                s.append(cls.getSimpleName()+',');
            }
            if(classes.length>0)
            s.deleteCharAt(s.length()-1);
            s.append(") { }\n");
        }
        System.out.println(s);
    }
}


输出结果为

 

通过反射机制调用方法

 

import java.lang.reflect.Method;
public class Test {
    public static void main(String[] args) throws Exception{
        Class userClass = Class.forName("User");
        //创建一个User类对象
        Object o = userClass.newInstance();
        //获取sum方法
        Method sum = userClass.getDeclaredMethod("sum", int.class, int.class);

        //调用sum方法
        int result =(int)sum.invoke(o,1,2);
        System.out.println(result);
    }
}

通过反射机制调用有参构造方法


import java.lang.reflect.Constructor;

public class Test {
    public static void main(String[] args) throws Exception{
        Class userClass = Class.forName("User");
        //调用无参构造方法创建对象
        Object o = userClass.newInstance();
        //调用有参构造方法创建对象
        Constructor constructor = userClass.getConstructor(int.class,String.class);
        Object o1 = constructor.newInstance(1111,"jack");

        System.out.println(o);
        System.out.println(o1);
    }
}

输出结果为

通过反射机制获取父类以及实现了什么接口

public class Test {
    public static void main(String[] args) throws Exception{
        Class stringClass = Class.forName("java.lang.String");
        //获取父类名
        Class superClass = stringClass.getSuperclass();
        System.out.println(superClass.getSimpleName());
        //获取实现了什么接口
        Class[] interfaces = stringClass.getInterfaces();
        for(Class i:interfaces){
            System.out.println(i.getSimpleName());
        }
    }
}

输出结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值