黑马程序员_反射

来源:互联网 发布:淘宝女士连衣裙 编辑:程序博客网 时间:2024/05/17 04:11
 ------- android培训java培训、期待与您交流! ----------

反射的概念:
    反射就是把Java类中的各种成分映射想成Java类。通过class文件的对象,获取构造函数、字段、方法的操作。
    例如:众多的人用一个Person类表示,那么众多的Java类就用一个Class类表示。
    反射也称之为对类的解剖。把类的各个组成部分映射成一个个相应的Java类。
学习反射的目的:
    有些时候,可能JDK中的方法没有在帮助文档中提供,但是通过查看源代码,却发现有这个方法,不会该方法为private私有,所
    以JDK的帮助文档没有提供该方法。如果必须使用这个方法,我们可以通过反射的方式来获取,进行使用。
得到某个class文件相对应的class对象的方法有3中:
    1、getClass():返回进行时的类。
       例如:new Date().getClass()。
    2、数据类型.class:静态属性,来获取当前数据类型的自解码文件对象。
       例如:Person.class.
    3、public static Class forName(String className):返回与带有给定字符串名的类或接口相关联的Class对象。
       例如:Class.forName("java.long.String");
代码示例:
public class ClassTest {public static void main(String[] args) throws ClassNotFoundException {String s = "黑马";//数据类型.class:静态属性,来获取当前数据类型的自解码文件对象,Class c1 = String.class;//getClass():返回进行时的类,Class c2 = s.getClass();//Class.forName(String className)返回与带有给定字符串名的类或接口相关联的Class对象。Class c3 = Class.forName("java.lang.String");System.out.println(c1 == c2);System.out.println(c2 == c3);}}

注意:字节码文件是唯一的,无论怎么获取,都是同一份字节码文件。

public class Person {private String name;int age;public String address;public Person(){}private Person(String name){this.name = name;}Person(String name, int age){this.name = name;this.age = age;}public Person(String name, int age, String address){this.name = name;this.age = age;this.address = address;}public void show(){System.out.println("show");}public void method(String s){System.out.println(s);}public String function(){return "function";}public int sum (int x, int y) {return x+y;}private void method(){System.out.println("私有的method");}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";}}
构造方法的反射应用(Constructor类):
    Constructor类的实例化对象代表类的一个构造方法。
    public Constructor[] getCOnstructors():反射所有的公共的构造方法
    public Constructor[] getDeclaredConstructors():获取所有的构造函数(包含私有)

    public Constructor getContructor(Class<?>... parameterTypes):获取指定的构造函数
    public Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):获取指定的构造函数(包含私有)
   
    public void setAccessible(boolean flag):是否可以访问(暴力访问)
    public Object newInstance(Object... initargs):使用此Constructor对象表示的构造方法来创建该构造方法的声明类的新实例,并用于指定的初始化该实例。

步骤:
    a:创建一个Class字节码文件对象
    b:获取指定的构造函数  如果是非public的构造函数,需要 强制访问(暴力访问)
    c:创建对象
    例如:

import java.lang.reflect.Constructor;public class ReflectDemo {public static void main(String[] args) throws ClassNotFoundException {//获取Person类的字节码文件对象Class c = Class.forName("com.itheima_02.Person");//public Constructor[] getConstructors() Constructor[] cons = c.getConstructors();for(Constructor con : cons){System.out.println(con);}System.out.println("-----------------");Constructor[] cons1 = c.getDeclaredConstructors(); for(Constructor con : cons1){  System.out.println(con); }}}
    其结果为:
        
    由结果可知:public Constructor[] getCOnstructors():反射所有的公共的构造方法  public Constructor[] getDeclaredConstructors():获取所有的构造函数(包含私有)
成员变量的反射(Field类):
    Class中的方法:
        public Field[] getFields() : 获取 public 修饰的 所有字段
        public Field[] getDeclaredFields(): 获取所有的字段(包含私有)
      
        public Field getField(String name): 获取指定的字段
        public Field getDeclaredField(String name): 获取指定的字段(包含私有)

    Field中的方法:
         public void set(Object obj, Object value):  为指定对象中的当前字段, 赋值
    步骤:
         a: 创建class字节码文件对象
         b: 获取指定的字段,如果是非public 修饰的字段, 需要 暴力访问
         c: 对字段进行操作
    举例验证上述方法:
import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;public class ReflectDemo {public static void main(String[] args) throws <span style="font-size:14px;"><span style="font-family:Simsun;"><span style="font-size:14px;"><span style="font-family:Simsun;"><span style="color:#330033;"><span style="LINE-HEIGHT: 21px"></span></span></span></span></span></span>Exception<span style="font-size:14px;"><span style="font-family:Simsun;"><span style="font-size:14px;"><span style="font-family:Simsun;"><span style="color:#330033;"><span style="LINE-HEIGHT: 21px"></span></span></span></span></span></span> {// 创建class字节码文件对象Class c = Class.forName("com.itheima_02.Person");//创建构造函数并创建对象Constructor con = c.getDeclaredConstructor();Object obj = con.newInstance();// Person//public Field[] getFields()Field[] fields = c.getFields();for (Field field : fields) {System.out.println(field);}System.out.println("-------");//public Field[] getDeclaredFields()Field[] fields1 = c.getDeclaredFields(); for (Field field : fields1) { System.out.println(field); }//public Field getField(String name): 获取指定的字段Field addressField = c.getField("address");System.out.println(obj);//public void set(Object obj, Object value):  为指定对象中的当前字段, 赋值addressField.set(obj, "北京");//private String name;Field nameField = c.getDeclaredField("name");nameField.setAccessible(true);//暴力访问nameField.set(obj, "黑马");System.out.println(obj);}}
    其结果为:
       

成员方法的反射(Method类):

    Class类中的方法:
        public Method[] getMethods() 获取所有的公共方法(包含父类的)
        public Method[] getDeclaredMethods() 获取所有的方法(不包含父类)

        public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法
        public Method getDeclaredMethod(String name, Class<?>... parameterTypes) : 获取指定的方法(包含私有的)

    Method类的方法:
          public Object invoke(Object obj, Object... args)
          调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了
          public void setAccessible(boolean flag)
    步骤:
        a: 创建class 字节码文件对象
        b: 获取指定的方法
        c: 使用方法(需要前有对象,才能使用方法)
      举例验证上述方法:
   
import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class ReflectDemo2 {public static void main(String[] args) throws Exception  {//创建class 字节码文件对象Class c = Class.forName("com.itheima_02.Person");//public Method[] getMethods() publicMethod[] methods = c.getMethods();for (Method method : methods) {System.out.println(method);}System.out.println("--------");//public Method[] getDeclaredMethods() 所有的Method[] methods1 = c.getDeclaredMethods(); for (Method method : methods1) { System.out.println(method); }/* * Person p = new Person(); * p.show(); */Constructor con = c.getConstructor();Object obj = con.newInstance();// Person//获取指定的方法//public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法Method showMethod = c.getMethod("show",null); //System.out.println(showMethod);//使用方法//public Object invoke(Object obj, Object... args)//调用给定的对象中的当前方法,并且给定方法的参数列表,这个时候就可以确定调用的是具体的哪一个方法了showMethod.invoke(obj, null);System.out.println("-----------------------------------------");//public void method(String s){}//public Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的方法Method meMethod = c.getMethod("method", String.class);//public Object invoke(Object obj, Object... args)meMethod.invoke(obj, "黑马");System.out.println("-----------------------------------------");//public String function(){}Method functionMethod = c.getMethod("function", null);String str = (String) functionMethod.invoke(obj,null);System.out.println(str);System.out.println("-----------------------------------------");//public int sum (int x, int y) {}Method sumMethod = c.getMethod("sum", int.class, int.class);int sum = (int) sumMethod.invoke(obj, 22, 11);System.out.println(sum);System.out.println("-----------------------------------------");//private void method(){}//Method me2Method = c.getMethod("method", null);Method me2Method = c.getDeclaredMethod("method", null);//暴力点me2Method.setAccessible(true);me2Method.invoke(obj, null);}}
    其结果为:
       

 ------- android培训java培训、期待与您交流! ----------
0 0
原创粉丝点击