反射

1.反射的介绍

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制,很多优秀的开源框架都是通过反射完成的。

Java反射机制,可以实现以下功能:

①在运行时判断任意一个对象所属的类;

②在运行时构造任意一个类的对象;

③在运行时判断任意一个类所具有的成员变量和方法;

④在运行时调用任意一个对象的方法;

⑤生成动态代理;

2.获取Class对象

Class 对象
在类加载到内容中时就有了表示这个类型的Class对象
Class对象是唯一的,不会改变的

 private int a;
    private String Uname;
    private String Upwd;
    public Demo(){

    }
    public Demo(double a){

    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "Demo{" +
                "a=" + a +
                ", Uname='" + Uname + '\'' +
                ", Upwd='" + Upwd + '\'' +
                '}';
    }

    private Demo(int a){
        this.a=a;
    }
    public Demo(String a){

    }
    public Demo(String uname, String upwd) {
        Uname = uname;
        Upwd = upwd;
    }

    public String getUname() {
        return Uname;
    }

    public void setUname(String uname) {
        Uname = uname;
    }

    public String getUpwd() {
        return Upwd;
    }

    public void setUpwd(String upwd) {
        Upwd = upwd;
    }



   public void a(){
        System.out.println("你好");
    }
    public void b(){
        System.out.println("世界");
    }
    private void c(){
        System.out.println("哈哈");
    }

2.1:对象.class

    Demo demo=new Demo();
    Class<?> c1=demo.getClass();
    System.out.println(c1.getName());

2.2:类.class

Class<?> c2=Demo.class;
System.out.println(c2.getName());

2.3:Class.forName()-->推荐使用这种方式

Class<?> c3=Class.forName("com.zh.reflect");
System.out.println(c3.getName());

2.4根据子类的对象获取父类

Class c4=c3.getSuperclass();
System.out.println(c4.getName());

2.5基本数据类型与包装类的对比

//基本数据类型的Class对象
System.out.println(int.class);
//基本数据类型的包装类都有一个TYPE
System.out.println(Integer.TYPE);
System.out.println(Integer.TYPE==int.class);

可以说明Class的对象是唯一的,不会改变

3.获得修饰符

返回此类或接口的Java语言修饰符,以整数编码。

Class<?> clz=Class.forName("com.zh.reflect.Demo");
int n=clz.getModifiers();
System.out.println(Modifier.toString(n));

4.创建对象

4.1获得构造器

根据Class对象,我们可以获得构造器,为实例化对象做准备。

getConstructor()--->获得public权限的构造器 返回一个Constructor对象

getConstructors()--->获得所有public权限的构造器,返回一个Constructor数组

getDeclaredConstructor()--->获得所有权限的构造器 返回一个Constructor对象

getDeclaredConstructors()--->获得所有权限的构造器 返回一个Constructor数组

Constructor<?> constructor = clz.getConstructor();//不给参数,默认调用参数空的构造器,如果没有,会报异常
System.out.println(constructor);
constructor=clz.getConstructor(String.class);--->获得一个带(String)的构造器
System.out.println(constructor);



Constructor<?>[] constructors=clz.getConstructors();
for(Constructor<?> c:constructors){
    System.out.println(c);
}



Constructor<?> declaredConstructor = clz.getDeclaredConstructor(int.class);//获得所有权限的带int参数的构造器
System.out.println(declaredConstructor);



Constructor<?>[] constructors=clz.getDeclaredConstructors();//获得所有权限的所有构造器
for(Constructor<?> c:constructors){
    System.out.println(c);
}

4.2实例化对象

4.2.1使用newInstance()

Class类中newInstance方法 内部创建对象时候默认调用空构造,没有空构造方法则抛出异常InstantiationException

Class<?> c= Class.forName("com.zh.reflect.Demo");
Demo demo = (Demo) c.newInstance();//实例化一个Demo类的对象
demo.setA(1);
demo.setUname("aaa");
demo.setUpwd("bbb");
System.out.println(demo);

4.2.2获取构造器,在调用构造器的newInstance()方法,并赋实参。

如果遇到private权限的构造器,使用constructor.setAccessible(true)方法忽略权限

Constructor constructor=c.getConstructor(String.class,String.class);//获取构造器
Demo demo=(Demo)constructor.newInstance("aaaa","cccc");//创建对象 指定使用这种构造器 赋初值
System.out.println(demo);



Constructor<?> constructor = c.getDeclaredConstructor(int.class);//获得带int类型参数的构造器
int modifiers = constructor.getModifiers();
System.out.println(Modifier.toString(modifiers));//输出修饰符
constructor.setAccessible(true);//如果是私有的内容,使用前忽略权限
Demo demo = (Demo)constructor.newInstance(3);
System.out.println(demo);

5.获得方法

getMethod(...)-->获得指定名字的公有方法 返回Method

getMethods()-->获得所有公有方法 返回Method [ ]数组

getDeclaredMethod(...)-->获得指定名字的所有修饰符的方法 返回Method

getDeclaredMethods()-->获得所有方法 返回Method [ ]数组

Demo demo=new Demo();
Class<?> classz=Class.forName("com.zh.reflect.Demo");
Method a = classz.getMethod("a");//获得叫 a的公有方法
System.out.println(a.getName());//获得方法名

调用方法 Object invoke(Object obj, Object... args)
成员方法 ->对象
静态方法 ->对象|类

a.invoke(demo);

如果是调用私有方法,一定也得调用a.setAccessible(true),忽略方法权限

Demo demo=new Demo();
Class<?> classz=Class.forName("com.zh.reflect.Demo");
Method c = classz.getDeclaredMethod("c");
c.setAccessible(true);
c.invoke(demo);

6.获得属性

getField(....)-->获得指定的公有属性 返回Field

getFields()-->获得所有的公有属性 返回Field [ ] 数组

getDeclaredField(...)-->获得指定所有修饰符的属性 返回 Field

getDeclaredFields(...)-->获得所有属性 返回 Field [ ] 数组

与方法类似 访问私有属性时 也要调用setAccessible()方法 忽略权限

Class classz=Class.forName("com.zh.reflect.Demo");
Demo demo =(Demo) classz.getConstructor(String.class, String.class).newInstance("aaa", "bbb");
Field uname = classz.getDeclaredField("Uname");
uname.setAccessible(true);//忽略权限
uname.set(demo,"aaa");//设置属性
System.out.println(uname.get(demo));//输出这个对象的所获得的这个属性的值

7.数组

操作数组需要借助Array类

String[] arr = (String[]) Array.newInstance(String.class,5);
System.out.println(arr.getClass().isArray());
//设置值
Array.set(arr,0,"胡歌");
//获取值
System.out.println(Array.get(arr,0));
System.out.println(Arrays.toString(arr));
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务