Java之反射

之前在 慕课网 上学习了反射,以代码的形式总结一下,写入博客:

代码片段1:几种类类型的表示方式
(解释类类型:万事万物皆对象,类也是对象,是Class类的实例对象,这个对象成为该类的类类型。)

import com.imooc.reflect.Foo;

class Foo{}

public class ClassDemo1 {
    public static void main(String[] args) {
        //Foo类的实例对象
        Foo f1 = new Foo();
        //Foo类也是实例对象,是Class类的实例对象,如何表示?
        //任何一个类都是Class的实例对象,这个实例对象有三种表示方式。

        //第一种表示--->任何一个类都有一个隐含的静态成员变量class
        Class c1 = Foo.class;
        //第二种表示 已经知道该类的对象,通过getClass方法
        Class c2 = f1.getClass();

        /*
         * c1,c2表示了Foo类的类类型(class type)
         * 万事万物皆对象,类也是对象,是Class类的实例对象,这个对象成为该类的类类型。
         * f1是Foo类的实例对象,c1,c2是Foo类的类类型。
         */
        System.out.println(c1 == c2);  //输出true

        //第三种表示
        try {
            Class c3 = Class.forName("com.imooc.reflect.Foo");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //通过类的类类型创建实例对象
        try {
            Foo foo2 = (Foo) c1.newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

代码片段2:得到类类型的名称

public class ClassDemo2 {
    public static void main(String[] args) {
        Class c1 = int.class;
        System.out.println(c1.getName()); //输出int
        Class c2 = double.class;
        Class c3 = Void.class;
        System.out.println(c2.getName()); //输出double
        System.out.println(c3.getSimpleName()); //输出Void
    }
}

代码片段3:

class A{
    public void print(){
        System.out.println("hello world!");
    }
    public void print(int a, int b){
        System.out.println(a+b);    
    }
    public void print(String a, String b){
        System.out.println(a.toUpperCase() + ", " + b.toLowerCase());
    }
}

public class ClassDemo4 {
    public static void main(String[] args) {
        A a = new A();
        Class c = a.getClass();
        try {
            //获取print(int a, int b)方法
            Method m = c.getDeclaredMethod("print", new Class[]{int.class, int.class});
            //或者可以写成
            Method m1 = c.getDeclaredMethod("print", int.class, int.class);
            //获取print(String a, String b)方法
            Method m2 = c.getDeclaredMethod("print", String.class,String.class);
            //获取print()方法
            Method m3 = c.getDeclaredMethod("print" );
            try {
                Object o = m1.invoke(a, 10,20);
                //如果print方法没有返回值,o为null,否则o为print的返回值
                System.out.println(o);
                System.out.println("========================");
                o = m2.invoke(a, "hello","world");
                System.out.println("========================");
                o = m3.invoke(a);   
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        //学习反射之前调用print(int a, int b)这样写:
        //a.print(10, 20);  //输出30
        //学习反射之后,可以用m调用print()方法    
    }

}

invoke方法的参数是:

invoke
public Object invoke(Object obj, Object... args)

代码片段4:反射会使泛型失效
(注:Java中集合的泛型,是防止错误输入的,只在编译阶段有效,绕过编译就无效了)

public class ClassDemo5 {
    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        ArrayList list1 = new ArrayList();
        ArrayList<String> list2 = new ArrayList<>();

        list2.add("hello");
        //list2.add(20);  //编译错误
        Class c1 = list1.getClass();
        Class c2 = list2.getClass();
        System.out.println(c1 == c2);  //输出true

        /*
         * 反射的操作都是编译之后的操作
         * c1 == c2结果返回true,说明编译之后集合的泛型是去泛型化的
         * Java中集合的泛型,是防止错误输入的,只在编译阶段有效,绕过编译就无效了
         * 验证:通过方法的反射来操作list,绕过编译,非String类型也能加入到list2中
         */

        try {
            Method m = c2.getMethod("add", Object.class);
            m.invoke(list2, 20); //实际上list2是只允许加入String类型的
            //打印输出list2的值,发现20也被加入了list2中
            System.out.println(list2);
            //将会报错,因为20不能转换为string类型
            for (String string : list2) {
                System.out.println(string);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值