java 反射

反射

java的动态机制,用于在运行期间检查对象的类型,检查对象的类结构(属性,方法等),还可以动态加载类,动态创建对象,动态访问属性和方法等。

反射是Java 的API.

public void print(Object obj){
      //动态反射API,动态检查obj引用的对象类型
       Class cls=obj.getClass();
       System.out.println(obj);
}

经典面试题目:Eclipse中快捷菜单用了什么技术实现的?
答案:反射技术,反射API

解耦
解除耦合性:降低/解除 两端代码(两个组件)之间的耦合关系
利用反射API,可以实现一个组件与未来的一个组件的松散耦合.甚至可以不在不知道
类名不知道方法名的情况下实现调用关系

反射的功能

1.动态加载类
2.动态创建对象
3.动态调用属性和方法

public class ReflectDemo01 {

    public static void main(String[] args) {
        print(1);
        print("1");
        print('1');
    }
    
    public static void print(Object obj){
        //动态检查obj对象的类型
        //getClass方法在Object类上定义,被所有对象继承,全部对象都有的方法
        Class cls=obj.getClass();
        /*
         * Class提供了更加详尽的类型详细信息
         * 检查方法:检查属性,检查方法,检查构造器.....
         * 动态检查Integer等类型的属性
         */
        //Declared:声明的  Field:字段,属性
        System.out.println("属性:------------------------");
        Field[] fields=cls.getDeclaredFields();
        for(Field field:fields){
            System.out.println(field);
        }
        System.out.println("方法:------------------------");
        //获取当前类型上声明的所有方法信息
        Method[] methods=cls.getDeclaredMethods();
        for(Method method:methods){
            System.out.println(method);
        }
        System.out.println(cls);
        System.out.println(obj);
    }

}

利用反射API动态加载类到方法区:

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

        Scanner in=new Scanner(System.in);
        System.out.println("输入类名:");
        String className=in.nextLine();
        /*
         * 动态加载类到方法区,如果类名错误则抛出“类没有找到的运行异常”
         */
        Class cls=Class.forName(className);
        System.out.println(cls);
        //进一步检查类的详细信息....
        Field[] file=cls.getDeclaredFields();
        for(Field f:file){
            System.out.println(f);
        }
        System.out.println("-----------------------");
        Method[] method=cls.getMethods();
        for(Method m:method){
            System.out.println(m);
        }
        /**
         * 利用反射API动态创建对象
         */
        Object obj=cls.newInstance();
        System.out.println(obj);

    }

}

执行一个类的全部以test为开头的方法,这些方法都是非静态方法,方法没有返回值,没有参数

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        
       //动态加载类
        Scanner in=new Scanner(System.in);
        System.out.println("输入类名:");
        String className=in.nextLine();
        Class cls=Class.forName(className);
        //动态创建对象
        Object obj=cls.newInstance();
        //动态检查类中的全部方法信息
        Method [] methods=cls.getDeclaredMethods();
        for(Method m:methods){
            //System.out.println(m);
            /*
             * method 代表一个方法的相关信息
             * method.getName()  返回方法名
             */
            String name=m.getName();
            //System.out.println(name);
            if(name.startsWith("test")){
                System.out.println("test开头:"+m);
                /*
                 * Access 访问
                 * Accessble可访问
                 * 可以打破封装,访问不可见的方法
                 */
                m.setAccessible(true);
                
                /*
                 * method.invoke() 方法用于在对象上调用(invoke)当前
                 * method对应的方法,必须传递包含方法的对象作为参数。
                 */
                Object val=m.invoke(obj,1);
                System.out.println(val);
            }
        }
    }

利用反射动态调用方法:

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        
        Scanner in=new Scanner(System.in);
        System.out.println("输入类名:");
        String className=in.nextLine();
        System.out.println("方法名:");
        String methodName=in.nextLine();
        System.out.println("参数类型:");
        String typeName=in.nextLine();
        System.out.println("参数值:");
        String paramValue=in.nextLine();
        
        //动态加载类
        Class cls=Class.forName(className);
        //参数类型转换
        Class type=null;  //方法的参数类型
        Object param=null;//调用方法时的实际参数
        if(typeName.equals("int")){
            //java中int的类型表示为:int.class
            type=int.class;
            param=Integer.parseInt(paramValue);
        }else if(typeName.equals("double")){
            type=double.class;
            param=Double.parseDouble(paramValue);
        }else if(typeName.equals("String")){
            type=String.class;
            param=paramValue;
        }
        //找到一个被执行的方法信息
        Method method=cls.getDeclaredMethod(methodName,type);
        //method.setAccessible(true);
        System.out.println(method);
        //动态创建对象
        Object obj=cls.newInstance();
        /*
         * 执行方法
         * obj代表包含方法的对象
         * param代表执行方法的时候的实际参数
         * param的数据类型要与type一致
        */
        Object value=method.invoke(obj, param);
        System.out.print(value);
        
        

    }

利用反射获取属性的值:

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
        Scanner in=new Scanner(System.in);
        System.out.println("类名:");
        String className=in.nextLine();
        System.out.println("属性名:");
        String name=in.nextLine();
        Class cls=Class.forName(className);
        //动态创建对象
        Object obj=cls.newInstance();
        //在类上查找指定的类信息
        Field fld=cls.getDeclaredField(name);
        //获取对象obj上的fld属性信息
        Object value=fld.get(obj);
        //输出属性的值
        System.out.println(value);

    }

获取字符串的char[] value属性
因为属性value是私有的,所以采用反射API访问:

public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        String s="落霞与孤鹜齐飞,秋水共长天一色。";
        //找到属性信息
        Class cls=String.class;
        Field fld=cls.getDeclaredField("value");
        fld.setAccessible(true);
        char [] chs=(char[])fld.get(s);
        for(char c:chs){
            System.out.println(c);
        }
//        chs[1]='好';
//        System.out.println(s);
                
    }

运行结果:

利用反射API动态设置对象的属性:

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
        Scanner in=new Scanner(System.in);
        System.out.println("类名:");
        String className=in.nextLine();
        System.out.println("属性:");
        String name=in.nextLine();
        System.out.println("值:");
        String value=in.nextLine();
        Class cls=Class.forName(className);
        Field fld=cls.getDeclaredField(name);
        Object obj=cls.newInstance();
        //设置obj对象的fld属性值为value
        fld.set(obj,value);
        System.out.println(obj);

    }

demo:

public class TestCase {

    public void testHello(){
        System.out.println("hello world!");
    }
    
    private void testKitty(){
        System.out.println("hello kitty!");
    }
    
    public void demo(){
        System.out.println("demo");
    }
}
public class Foo {
    public int age=3;
    private String name;
    private int salary;
    private String gender;
    public Foo(){
        
    }
    @Override
    public String toString() {
        return "Foo [age=" + age + ", name=" + name + ", salary=" + salary + ", gender=" + gender + "]";
    }
    public Foo(int age, String name, int salary, String gender) {
        super();
        this.age = age;
        this.name = name;
        this.salary = salary;
        this.gender = gender;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((gender == null) ? 0 : gender.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + salary;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Foo other = (Foo) obj;
        if (age != other.age)
            return false;
        if (gender == null) {
            if (other.gender != null)
                return false;
        } else if (!gender.equals(other.gender))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (salary != other.salary)
            return false;
        return true;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    

}
public class Goo {
     private int test(int a){
         return a+1;
      }
      public String demo(String s){
         return s+"";
      }
      public double demo(double d){
         return d+1;
      }
}
public class Person {

    String name;
    
    String sex;

    @Override
    public String toString() {
        return "Person [name=" + name + ", sex=" + sex + "]";
    }
    
}
原文地址:https://www.cnblogs.com/jyy599/p/12093893.html