黑马程序员技术交流社区

标题: 【上海校区】玩转Java 反射 [打印本页]

作者: biu波儿了罢    时间: 2019-5-9 15:21
标题: 【上海校区】玩转Java 反射
本帖最后由 biu波儿了罢 于 2019-5-9 15:31 编辑

玩转 Java 反射

类加载器
- 什么是类加载器
- 类加载器的职责
- 类加载器的组成

反射
- 什么是反射
- 如何使用反射
- 反射在Android中的应用

什么是类加载器
当Java程序要使用某个类时,如果该类还没有被加载到内存中,则系统会通过加载,链接,吃实话这三步来实现对这个类进行初始化。
加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会创建一个Class对象。
链接
验证 是否有正确的内部结构,并和其他类协调一致。
准备 负责为类的静态成员分配内存,并设置默认初始化值。
解析 将累的二进制数据中的符号引用替换为直接引用。
初始化
类的初始化,不做过多叙述
类的初始化时机 (什么时候会被加载到内存)
当以上条件满足任意一条时,类就会被初始化
类加载器的职责
负责将.class 文件加载待内存中,并产生Class对象。

类加载器的组成
什么是反射

描述
java.lang.Class描述编译后的class文件的对象
java.lang.reflect.Constructor用于描述构造方法
java.lang.reflect.Field描述字段(成员变量)
java.lang.reflect.Method描述成员方法

如何使用反射
A . 使用Class类,获取出被解剖的这个类的class文件对象
B . 使用Class类方法,获取出类中的所有成员
C . 将成员获取出来后,交给对应类,对应类中的方法,运行成员

如何获取,class文件对象
不管用哪种方式获取的Class对象,他们都是相等的。
[Java] 纯文本查看 复制代码
package com.test.demo;
/**
* 定义person类
*/
public class Person {

}

package com.test.demo;

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {

        

        Person p1=new Person();
        Class cc=p1.getClass();
        System.out.println(cc);

        
        Class cc2=Person.class;
        System.out.println(cc2);
        
        Class cc3=Class.forName("com.test.demo.Person");
        System.out.println(cc3);

        System.out.println(cc==cc2);
        System.out.println(cc2==cc3);
    }
}



class com.test.demo.Person
class com.test.demo.Person
class com.test.demo.Person
true
true
获取构造
[Java] 纯文本查看 复制代码
为Person类增加构造

public Person(){
        System.out.println("Person类无参数构造");
    }
    public Person(int a,int b,String s){
        System.out.println("Person类有参数构造:a:"+a+" b:"+b+" s:"+s);
    }

    private Person(int a){
        System.out.println("Person类有参数   私有 构造:a:"+a);
    }



package com.test.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        Class clazz=Person.class;
        
        Constructor [] conarr=clazz.getConstructors();

        for(Constructor con :conarr){
            System.out.println(con);
        }
        
        
        Constructor cc=clazz.getConstructor();
        Object oo=cc.newInstance();

        
        Constructor cc2=clazz.getConstructor(int.class,int.class,String.class);
        Object oo2=cc2.newInstance(1,2,"haha");

        
        Constructor cc3=clazz.getDeclaredConstructor(int.class);
        
        cc3.setAccessible(true);
        Object oo3=cc3.newInstance(1);

        clazz.newInstance();
    }
}

输出结果
public com.test.demo.Person()
public com.test.demo.Person(int,int,java.lang.String)
Person类无参数构造
Person类有参数构造:a:1 b:2 s:haha
Person类有参数   私有 构造:a:1
Person类无参数构造

获取成员变量
[Java] 纯文本查看 复制代码
为Person类增加成员变量

    public String name="smt";
    private String idcard="1001u09t";

    @Override
    public String toString() {
        
        return "name:"+name+"  idcard:"+idcard;
    }

package com.test.demo;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException,
            NoSuchMethodException, SecurityException, InstantiationException,
            IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchFieldException {

        Class clazz = Person.class;
        Object obj = clazz.newInstance();
        
        Field[] fields = clazz.getFields();
        for(Field s:fields){
            System.out.println(s);
        }

        Field field=clazz.getField("name");

        field.set(obj, "haha");

        System.out.println(obj);

        Field field2=clazz.getDeclaredField("idcard");
        field2.setAccessible(true);
        field2.set(obj, "123456");
        System.out.println(obj);
    }
}

输出结果
Person类无参数构造
public java.lang.String com.test.demo.Person.name
name:haha  idcard:1001u09t
name:haha  idcard:123456

获取成员方法
[Java] 纯文本查看 复制代码
 为Person类增加成员方法

    public void show(){
        System.out.println("show 空参数");
    }
    public void show(int a){
        System.out.println("show   a:"+a);
    }   
    private void show(String s){
        System.out.println("show   s:"+s);
    }

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException,
            NoSuchMethodException, SecurityException, InstantiationException,
            IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchFieldException {


        Class clazz = Person.class;
        Object obj = clazz.newInstance();
        
        Method [] methods=clazz.getMethods();

        for(Method m:methods){
            System.out.println(m);
        }

        Method m=clazz.getMethod("show");
        m.invoke(obj);

        Method m1=clazz.getMethod("show",int.class);
        m1.invoke(obj,1);

        Method m2=clazz.getDeclaredMethod("show",String.class);
        m2.setAccessible(true);
        m2.invoke(obj,"smt");
    }
}


输出结果:
Person类无参数构造
public java.lang.String com.test.demo.Person.toString()
public void com.test.demo.Person.show(int)
public void com.test.demo.Person.show()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
show 空参数
show   a:1
show   s:smt


反射在Android中的应用
设置菜单中图标的显示
[Java] 纯文本查看 复制代码
@Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
            if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
                try {
                    Method m = menu.getClass().getDeclaredMethod(
                            "setOptionalIconsVisible", Boolean.TYPE);
                    m.setAccessible(true);
                    m.invoke(menu, true);
                } catch (Exception e) {
                }
            }
        }
        return super.onMenuOpened(featureId, menu);
    }

设置前和设置后的对比



文章转载自:https://juejin.im/entry/57c3dd6279bc440063e7d59f







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2