反射基础

类的加载

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

加载

就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象。

连接

验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
初始化 就是我们以前讲过的初始化步骤

/*
* 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
*
* Person p = new Person();
* p.使用
*
* 要想这样使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。
* Class类:
* 成员变量 Field
* 构造方法 Constructor
* 成员方法 Method
*
* 获取class文件对象的方式:
* A:Object类的getClass()方法
* B:数据类型的静态属性class
* C:Class类中的静态方法
* public static Class forName(String className)
*
* 一般我们到底使用谁呢?
* A:自己玩 任选一种,第二种比较方便
* B:开发 第三种
* 为什么呢?因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
*/

    public class ReflectDemo {
        public static void main(String[] args) throws ClassNotFoundException {
            // 方式1
            Person p = new Person();
            Class c = p.getClass();

            Person p2 = new Person();
            Class c2 = p2.getClass();

            System.out.println(p == p2);// false
            System.out.println(c == c2);// true

            // 方式2
            Class c3 = Person.class;
            // int.class;
            // String.class;
            System.out.println(c == c3);

            // 方式3
            // ClassNotFoundException
            Class c4 = Class.forName("cn.itcast_01.Person");
            System.out.println(c == c4);
        }
    }

/*
 * 通过反射获取构造方法并使用。
 */
public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");
        // 获取构造方法
        // public Constructor[] getConstructors():所有公共构造方法
        // public Constructor[] getDeclaredConstructors():所有构造方法
        // Constructor[] cons = c.getDeclaredConstructors();
        // for (Constructor con : cons) {
        // System.out.println(con);
        // }

    // 获取单个构造方法
    // public Constructor<T> getConstructor(Class<?>... parameterTypes)
    // 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
    Constructor con = c.getConstructor();// 返回的是构造方法对象

    // Person p = new Person();
    // System.out.println(p);
    // public T newInstance(Object... initargs)
    // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
    Object obj = con.newInstance();
    System.out.println(obj);

    // Person p = (Person)obj;
    // p.show();
}

}


/*
 * 需求:通过反射去获取该构造方法并使用:
 * public Person(String name, int age, String address)
 * 
 * Person p = new Person("林青霞",27,"北京");
 * System.out.println(p);
 */
public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

    // 获取带参构造方法对象
    // public Constructor<T> getConstructor(Class<?>... parameterTypes)
    Constructor con = c.getConstructor(String.class, int.class,
            String.class);

    // 通过带参构造方法对象创建对象
    // public T newInstance(Object... initargs)
    Object obj = con.newInstance("林青霞", 27, "北京");

    System.out.println(obj);
}

}


/*
 * 需求:通过反射获取私有构造方法并使用
 * private Person(String name){}
 * 
 * Person p = new Person("风清扬");
 * System.out.println(p);
 */
public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");
    // 获取私有构造方法对象
    // NoSuchMethodException:每个这个方法异常
    // 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。
    Constructor con = c.getDeclaredConstructor(String.class);

    // 用该私有构造方法创建对象
    // IllegalAccessException:非法的访问异常。
    // 暴力访问
    con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
    Object obj = con.newInstance("风清扬");

    System.out.println(obj);
}

}


/*
 * 通过发生获取成员变量并使用
 */
public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

    // 获取所有的成员变量
    // Field[] fields = c.getFields();
    // Field[] fields = c.getDeclaredFields();
    // for (Field field : fields) {
    // System.out.println(field);
    // }

    /*
     * Person p = new Person(); p.address = "北京"; System.out.println(p);
     */

    // 通过无参构造方法创建对象
    Constructor con = c.getConstructor();
    Object obj = con.newInstance();
    System.out.println(obj);

    // 获取单个的成员变量
    // 获取address并对其赋值
    Field addressField = c.getField("address");
    // public void set(Object obj,Object value)
    // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
    addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
    System.out.println(obj);

    // 获取name并对其赋值
    // NoSuchFieldException
    Field nameField = c.getDeclaredField("name");
    // IllegalAccessException
    nameField.setAccessible(true);
    nameField.set(obj, "林青霞");
    System.out.println(obj);

    // 获取age并对其赋值
    Field ageField = c.getDeclaredField("age");
    ageField.setAccessible(true);
    ageField.set(obj, 27);
    System.out.println(obj);
}

}


public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

    // 获取所有的方法
    // Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
    // Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
    // for (Method method : methods) {
    // System.out.println(method);
    // }

    Constructor con = c.getConstructor();
    Object obj = con.newInstance();

    /*
     * Person p = new Person(); p.show();
     */

    // 获取单个方法并使用
    // public void show()
    // public Method getMethod(String name,Class<?>... parameterTypes)
    // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
    Method m1 = c.getMethod("show");
    // obj.m1(); // 错误
    // public Object invoke(Object obj,Object... args)
    // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
    m1.invoke(obj); // 调用obj对象的m1方法

    System.out.println("----------");
    // public void method(String s)
    Method m2 = c.getMethod("method", String.class);
    m2.invoke(obj, "hello");
    System.out.println("----------");

    // public String getString(String s, int i)
    Method m3 = c.getMethod("getString", String.class, int.class);
    Object objString = m3.invoke(obj, "hello", 100);
    System.out.println(objString);
    // String s = (String)m3.invoke(obj, "hello",100);
    // System.out.println(s);
    System.out.println("----------");

    // private void function()
    Method m4 = c.getDeclaredMethod("function");
    m4.setAccessible(true);
    m4.invoke(obj);
}

}


/*
 * 通过配置文件运行类中的方法
 * 
 * 反射:
 *      需要有配置文件配合使用。
 *      用class.txt代替。
 *      并且你知道有两个键。
 *          className
 *          methodName
 */
public class Test {
    public static void main(String[] args) throws Exception {
        // 反射前的做法
        // Student s = new Student();
        // s.love();
        // Teacher t = new Teacher();
        // t.love();
        // Worker w = new Worker();
        // w.love();
        // 反射后的做法

    // 加载键值对数据
    Properties prop = new Properties();
    FileReader fr = new FileReader("class.txt");
    prop.load(fr);
    fr.close();

    // 获取数据
    String className = prop.getProperty("className");
    String methodName = prop.getProperty("methodName");

    // 反射
    Class c = Class.forName(className);

    Constructor con = c.getConstructor();
    Object obj = con.newInstance();

    // 调用方法
    Method m = c.getMethod(methodName);
    m.invoke(obj);
}

}


/*
 * 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
 */
public class ArrayListDemo {
    public static void main(String[] args) throws NoSuchMethodException,
            SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        // 创建集合对象
        ArrayList<Integer> array = new ArrayList<Integer>();

    // array.add("hello");
    // array.add(10);

    Class c = array.getClass(); // 集合ArrayList的class文件对象
    Method m = c.getMethod("add", Object.class);

    m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
    m.invoke(array, "world");
    m.invoke(array, "java");

    System.out.println(array);
}

}


public class Tool {
    public void setProperty(Object obj, String propertyName, Object value)
            throws NoSuchFieldException, SecurityException,
            IllegalArgumentException, IllegalAccessException {
        // 根据对象获取字节码文件对象
        Class c = obj.getClass();
        // 获取该对象的propertyName成员变量
        Field field = c.getDeclaredField(propertyName);
        // 取消访问检查
        field.setAccessible(true);
        // 给对象的成员变量赋值为指定的值
        field.set(obj, value);
    }
}
public class ToolDemo {
    public static void main(String[] args) throws NoSuchFieldException,
            SecurityException, IllegalArgumentException, IllegalAccessException {
        Person p = new Person();
        Tool t = new Tool();
        t.setProperty(p, "name", "林青霞");
        t.setProperty(p, "age", 27);
        System.out.println(p);
        System.out.println("-----------");

    Dog d = new Dog();

    t.setProperty(d, "sex", '男');
    t.setProperty(d, "price", 12.34f);

    System.out.println(d);
}
}

class Dog {
    char sex;
    float price;

@Override
public String toString() {
    return sex + "---" + price;
}
}

class Person {
    private String name;
    public int age;

@Override
public String toString() {
    return name + "---" + age;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值