黑马程序员——【Java高新技术】——反射机制

---------- android培训java培训、期待与您交流! ----------

一、概述

  1、Java反射机制:是指“在运行状态中”,对于任意一个类,都能够知道这个类中的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

  2、Java反射机制主要提供了以下功能:

  (1)在运行时,判断任意一个对象所属的类

  (2)在运行时,构造任意一个类的对象

  (3)在运行时,判断任意一个类所具有的成员变量和方法(通过反射实现)。

  (4)在运行时,调用任意一个对象的方法(注意:前提都是在运行时,不是在编译时)

  3、反射:是对类进行解剖,将Java类中的各种构成成分映射成相应的java类。

  一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示。表示java类的Class类提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等。

二、反射的基石——Class

  (一)概述

  所有的类文件都有共同属性,所以可以向上抽取,把这些共性内容封装成一个类,这个类就叫Class。Class类中就包含属性有field(字段)、method(方法)、construction(构造函数)。

  (二)Class和class的区别

   1、class:Java中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。

   2、Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。Class是Java程序中各个Java类的总称;它是反射的基石,通过Class类来使用反射。

  (三)获取Class对象的三种方式:

   1、Object类中的getClass()方法(这种方式必须要明确具体的类,并创建对象,较麻烦),例如:

    Person p = new Person();

    Class clazz = p.getClass();

   2、通过任何数据类型都具备的一个静态属性.class来获取其对应的Class对象(这种方式相对简单,但是还是要明确用到类中的静态成员,不够扩展)。

    Class clazz = Person.class;

   3、可以使用Class类中的forName()方法完成,扩展性更强(这种方式只要通过给定的类的“字符串名称”就可以获取该类对象,更为扩展)

    String className = “包名.类名”;

    Class clazz = Class.forName(className);

    // * 如何产生空参对象?

    Object obj = clazz.newInstance();

  (四)基本的Class对象

   1、九个预定义的Class:

   (1)包括八种基本类型(byte、short、int、long、float、double、char、boolean)的字节码对象和一种返回值为void类型的void.class。

   (2)Integer.TYPE:表示基本类型 int 的 Class 实例,和int.class是相等的。基本数据类型的字节码都可以用与之对应的包装类中的TYPE常量表示

   2、只要是在源程序中出现的类型都有各自的Class实例对象,如int[].class。数组类型的Class实例对象,可以用Class.isArray()表示。

  (五)Class类中的方法

   1、static Class forName(String className):1、返回与给定字符串名的类或接口的相关联的Class对象。

   2、Class getClass():返回的是Object运行时的类,即返回Class对象即字节码对象

   3、Constructor getConstructor():返回Constructor对象,它反映此Class对象所表示的类的指定公共构造方法。

   4、Field getField(String name):返回一个Field对象,它表示此Class对象所代表的类或接口的指定公共成员字段。

   5、Field[] getFields():返回包含某些Field对象的数组,表示所代表类中的成员字段。

   6、Method getMethod(String name,Class… parameterTypes):返回一个Method对象,它表示的是此Class对象所代表的类的指定公共成员方法。

   7、Method[] getMehtods():返回一个包含某些Method对象的数组,是所代表的的类中的公共成员方法。

   8、String getName():以String形式返回此Class对象所表示的实体名称。

   9、String getSuperclass():返回此Class所表示的类的超类的名称

   10、boolean isArray():判定此Class对象是否表示一个数组

   11、boolean isPrimitive():判断指定的Class对象是否是一个基本类型。

   12、T newInstance():创建此Class对象所表示的类的一个新实例。

  (六)代码示例:

package cn.itheima;
class Person {
    private String name;
    public int age;
    public Person(){
        System.out.println("Person run");
    }
    public Person(String name,int age){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return name+":"+age;
    }
}
public class ClassDemo{
    public static void main(String[] args) throws Exception {
        // 获取类的全名称字符串
        String className = "cn.itheima.Person";

        // 获取Person类的Class对象
        Class clazz = Class.forName(className);

        // 通过newInstance方法获取类的无参构造函数实例
        Person p = (Person)clazz.newInstance();
    }
}

三、Constructor

  (一)概述

   Constructor代表某个类的一个构造方法。

  (二)构造方法

   1、得到这个类的所有构造方法:例如:Constructor[] cons = Class.forName (“java.lang.String”) . getConstructors ();

   2、得到某一个构造方法:Constructor con = String.class.getConstructor (String.class , int.class);

  (三)创建实例对象

   1、通常方式:String str = new String ( new StringBuffer(“abc”));

   2、反射方式:String str = (String) constructor.newInstance ( new StringBuffer (“abc”));

   注:

   (1)创建实例时newInstance方法中的参数列表必须与获取Constructor的方法getConstructor方法中的参数列表一致。

   (2)newInstance():构造出一个实例对象,每调用一次就构造一个对象。

   (3)利用Constructor类来创建类实例的好处是可以指定构造函数,而Class类只能利用无参构造函数创建类实例对象。

  (四)代码示例

package cn.itheima;
class Person {
    private String name;
    public int age;
    public Person(){
        System.out.println("Person run");
    }
    public Person(String name,int age){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return name+":"+age;
    }
}
//通过Constructor对象来创建类实例方法
public static void ConstructorDemo() throws Exception{
    //获取Person类的Class对象
    String name = "cn.itheima.Person";
    Class clazz = Class.forName (name);
    //Class clazz = Person.class;
    //获取指定构造函数的类实例
    Constructor con = clazz.getConstructor (String.class , int.class);
    Person p = (Person) con.newInstance("lisi",30);
    System.out.println (p.toString());
}

四、Field

  (一)概述:Field类代表某个类中一个成员变量

  (二)方法

   1、Field getField(String s):只能获取公有和父类中公有

   2、Field getDeclaredField(String s):获取该类中任意成员变量,包括私有

   3、setAccessible(ture)://如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。

   4、set(Object obj, Object value):将指定对象变量上此Field对象表示的字段设置为指定的新值。

   5、Object get(Object obj):返回指定对象上Field表示的字段的值。

  (三)代码示例

 1 package cn.itheima;
 2 class Person {
 3     private String name;
 4     public int age;
 5     public Person(){
 6         System.out.println("Person run");
 7     }
 8     public Person(String name,int age){
 9         this.age = age;
10         this.name = name;
11     }
12     public String toString(){
13         return name+":"+age;
14     }
15 }
16 //获取Person对象的成员变量
17 public static void getPersonField() throws Exception{
18 //如果想要给该变量赋值,必须先要有对象。
19     Class clazz = Class.forName("cn.itheima.Person");
20     Person p = (Person)clazz.newInstance();
21     //获取所有的成员变量
22     Field[] fs = clazz.getFields();
23     for(Field f:fs){
24         System.out.println(f);
25     }
26     //获取指定的成员变量
27     Field fage = clazz.getField("age");
28     Field fname = clazz.getDeclaredField("name");
29     //显示改变后的值
30     fage.set(p, 20);
31     System.out.println(fage.get(p));
32     //暴力访问私有变量
33     fname.setAccessible(true);
34     fname.set(p, "zhangsan");
35     System.out.println(fname.get(p));
36 }

五、Method

  (一)概述:Method类代表某个类中成员方法。调用某个对象身上的方法,要先得到方法,再针对某个对象调用。

  (二)方法

   Method[] getMethods():只获取公共和父类中的方法。

   Method[] getDeclaredMethods():获取本类中包含私有。

   Method getMethod("方法名",参数.class(如果是空参可以写null));

   Object invoke(Object obj ,参数):调用方法

   注:① invoke方法:如果底层是静态的,那么可以忽略指定的obj参数,填充为null。② 如果底层方法所需的“形式参数”为0,则所提供的args数组长度可以为0或null。

  (三)获取类中方法

   1、通常方式:对象名.函数。如str.charAt(int index);

   2、反射方式:

   Method MethodCharAt = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);

   3、反射调用底层方法:charAtMethod.invoke(str, int index);

   说明:如果传递给Method对象的invoke()方法的第一个参数为null,说明Method对象对应的是一个静态方法

  (四)代码应用示例

package cn.itheima;
class Person {
    private String name;
    public int age;
    public Person(){
        System.out.println("Person run");
    }
    public Person(String name,int age){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return name+":"+age;
    }
}
public static void getPersonMethod() throws Exception{
    //如果想要获取方法,必须先要有对象。
    Class clazz = Class.forName("cn.itheima.Person");
    //获取所有方法
    Method[] methods = clazz.getMethods();//只获取公共的和父类中的。
    //methods = clazz.getDeclaredMethods();//获取本类中所有的方法,包含私有。
    for(Method method : methods){
        System.out.println(method);
    }
    //获取单个方法
    Method me=clazz.getMethod("toString", null);
    Object returnVaule=me.invoke(p, null);
    System.out.println(returnVaule);
}

六、数组的反射

  (一)概述

   1、具有相同维数和元素类型的数组属于同一个类型,具有相同的Class实例对象。数组字节码的名字:有[和数组对应类型的缩写,如int[]数组的名称为:[I

   2、基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。

   3、如何得到某个数组中的某个元素的类型?

   例如:Object[] obj=new Object[]{“ABC”,1};无法得到某个数组的具体类型,只能得到其中某个元素的类型,如:Obj[0].getClass().getName() 得到的是java.lang.String。

   4、Arrays.asList()方法,在处理int[]是String[]时,是不同的。它会将int[]整体作为一个对象元素存入list集合。而会将String[]数组中的每一个字符串元素当做对象存入list集合。

   5、Array工具类(java.lang.reflect.Array)用于完成对数组的反射操作,它提供了动态创建和访问Java数组的方法:如

     Array.getLength(Object obj);//获取数组的长度

    Array.get(Object obj,int x);//获取数组中的元素

  (二)数组反射代码示例

 1 import java.lang.reflect.Array;
 2 import java.util.Arrays;
 3 public class ArrayReflect {
 4     public static void main(String[] args) {
 5         int [] a1 = new int[]{1,2,3};
 6         int[][] a2 = new int[2][3];
 7         String [] a3 = new String[]{"a","b","c"};
 8         Object obj1 = a1;
 9         Object obj2 = a3;
10         Object obj3 = a4;
11         //Array工具类用于完成对数组的反射操作。如打印任意数值
12         printObject(a1);
13         printObject(a4);
14         printObject("abc");
15 }
16     //打印任意数值
17     private static void printObject(Object obj) {
18         Class clazz = obj.getClass();
19         //如果传入的是数组,则遍历
20         if(clazz.isArray()){
21             int len = Array.getLength(obj);//Array工具类获取数组长度方法
22             for(int x = 0;x<len;x++){
23                 System.out.println(Array.get(obj, x));//Array工具获取数组元素
24             }
25         }
26         else
27             System.out.println(obj);
28     }
29 }

七、反射的作用——实现框架功能

  (一)概述

   1、框架:通过反射调用Java类的一种方式。框架如同地产商建造房子,门窗和空调等等内部装修都由用户自己安装。房子就是框架,用户需使用此框架,安好门窗等放入到房地产商提供的框架中。

   注:框架和工具类的区别在于工具类被用户类调用,而框架是调用用户提供的类。

   2、框架要解决的核心问题

   我们在写框架的时候,调用的类还未出现,那么框架无法知道要被调用的类名,所以在程序中无法直接new某个类的实例对象,而要通过反射来做。

  (二)简单框架的创建步骤:

   1、创建一个配置文件,在Eclipse的java项目面板中:

   “右键”——“New”——选择“File“,file name命名为config.properties,然后写入配置信息。如className=java.util.ArrayList,等号右边是配置键,右边是值。

   2、代码实现,加载此文件:

   ① 将文件读取到读取流中,要写出配置文件的路径(相对路径或绝对路径)。如:InputStream ips = new FileInputStream(“config.properties”);

   ② 用Properties类的load()方法将流中的数据装载入集合。

   ③ 关闭流资源:关闭的是读取流,因为流中的数据已经加载进内存。

   3、通过getProperty()方法获取className,即配置的值,也就是某个类名。

   4、用反射的方式,创建对象newInstance()。

   5、执行程序主体功能

八、类加载器方式管理资源和配置文件

  (一)概述

   1、类加载器:是将.class的文件加载进内存,也可将普通文件中的信息加载进内存。

   2、文件的加载细节:

   (1)eclipse会将源程序中的所有.java文件编译成.class文件,然后放到classPath指定的目录中去。并且会将非.java文件原封不动的复制到.class指定的目录中去。在运行的时候,执行的是.class文件。

   (2)将配置文件放到.class文件目录中一同打包,类加载器就会一同加载。

   3、使用类加载器加载“资源文件“。

   (1)由类加载器ClassLoader来加载进内存,即用getClassLoader()方法获取类加载器,然后用类加载器的getResourceAsStream(String name)方法,将配置文件(资源文件)加载进内存。利用类加载器来加载配置文件,需把配置文件放置的包名一起写上。这种方式只有读取功能。

   (2)Class类也提供getResourceAsStream方法来加载资源文件,其实它内部就是调用了ClassLoader的方法。这时,配置文件是相对类文件的当前目录的,也就是说用这种方法,配置文件前面可以省略包名。

   如:类名.class.getResourceAsStream(“资源文件名”)

   4、配置文件的路径问题:

   (1)用绝对路径,通过getRealPath()方法运算出来具体的目录

   一般先得到用户自定义的总目录,在加上自己内部的路径。可以通过getRealPath()方法获取文件路径。对配置文件修改是需要要储存到配置文件中,那么就要得到它的绝对路径才行,因此,配置文件要放到程序的内部。

   (2)name的路径问题:

    ① 如果配置文件和classPath目录没关系,就必须写上绝对路径,

    ② 如果配置文件和classPath目录有关系,即在classPath目录中或在其子目录中(一般是资源文件夹resource),那么就得写相对路径,因为它自己了解自己属于哪个包,是相对于当前包而言的。

  (二)代码示例

import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;
class ClassLoaderDemo {
      public static void main(String[] args) throws Exception{
        Properties props = new Properties();
        InputStream ips = ClassLoaderDemo.class.getResourceAsStream ("/cn/itheima/day01/config.properties");
        props.load(ips);
        ips.close();

        String className = props.getProperty("className");
        Class clazz = Class.forName(className);

        Collection collection = (Collection)clazz.newInstance();

        collection.add("abc");
        collection.add("def");
        collection.add("ghk");
        collection.add("usa");

        System.out.println(collection.size());
    }
}

---------- android培训java培训、期待与您交流! ----------

时间: 2024-08-27 17:16:15

黑马程序员——【Java高新技术】——反射机制的相关文章

黑马程序员——Java高新技术——反射机制

点击打开链接 点击打开链接 点击打开链接 android培训.<a">点击打开链接 点击打开链接 java培训.期待与您交流!">点击打开链接 点击打开链接 反射的基石--Class类 Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class. Class类没有构造函数,不能new对象.怎么得到Class类的实例,有3中方法: ①类名.Class    Class  c1=Date.class; ②对象.getClass 获取对象所属的字

黑马程序员----java基础--反射机制

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.反射的基本描述 Java反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制.动态获取类中信息,就是java反射.可以理解为对类的解剖.如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术. 简单一

黑马程序员——JAVA高新技术——反射

----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 一.对于反射的概念 对于JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. JAVA反射(放射)机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言".从这个观点看,Perl,Python,Ruby

黑马程序员——Java高新技术——反射的复写

由于第一段视频学习效果不理想,希望重新看一遍反射视频,并多方面寻找资料,重新写一遍总结,以期java能力早日提高. Java——反射 一.Class类 Class 类的实例表示正在运行的 Java 应用程序中的类和接口.所以,Class可以提供方法获得动态的java类中的各个属性: (由定义可以知道Class创建的思路就是获得某一个特定java类的信息然后传给Class的对象,那么具体怎么做呢?) 这里说得java类的信息指的就是该java类的计算机的字节码:传给 Class cls1: 所以有

黑马程序员——java基础——反射

 黑马程序员--java基础--反射 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 反射 其实就是动态加载一个指定的类,并获取该类中的所有的内容.而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员. 反射就是把Java类中的各种成分映射成相应的java类. 简单说:反射技术可以对一个类进行解剖. 反射的基石-->Class类 1.java中的类是用来描述一类事物的共性,该类事物有什么属性,没有什么属性

黑马程序员——Java高新技术代理

代理 普通代理 很多时候,我们使用别人代码往往会发现别人代码的功能并不是十分符合我们的需求,调用别人的方法的时候,总是先new一个对象,然后我们的前处理做完,然后调用别人代码的方法,再加入后处理,这样做往往十分麻烦.代理就为其他类提供了一种控制其对象的方法.代理类和委托类必须实现同一个接口,这样代理类才能在需要的时候代替委托类对象,执行委托类的方法. interface Solution{ public void doSomething(); } //委托类Demo实现了接口 class Dem

黑马程序员----Java高新技术之反射学习总结

------- android培训.java培训.期待与您交流! ---------- 反射的概念. 1.Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 精妙的总结就是:反射就是将Java类中的各个成分映射成相应的Java类. 3.在Java中,描述事物的各种类同样也是一种事物,也可以用面向对象的方法来描述,即也有一个类来描述众多的J

黑马程序员——JAVA基础-反射

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 反射是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都只能都调用它的任意一个 方法和属性,这种动态获取的信息一级动态调用对象的方法的功能呢个称为java 的反射机制. 反射其实就是动态加载一个指定的类,并获取该类中的所有的内容.而且将字节码文件封装成对象, 并将字节码文件中的内容都封装成对象,这样便于操作这些成员.就是把JAVA类中的各种成

黑马程序员-java基础-反射基础

------- android培训.java培训.期待与您交流! ---------- java的反射机制是java的特性之一,反射机制是构建框架技术的基础所在,使用反射可以使程序更加灵活,避免将程序写死在代码里.相对于很多初学者只接触过java基础的人,反射还是一个很朦胧难懂的概念,下面我们就来说一下反射的一些应用. java反射机制是指在运行状态中,动态获取信息以及动态调用对象方法的功能.java反射有3个动态性质:1.运行时生成对象实例,2.运行期间调用发放,3.运行时更改属性. 那么反射

黑马程序员——java高新技术(新特性、反射、泛型)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- java高新技术 第一部分——JDK1.5新特性 1.增强for循环 格式: for(元素类型 变量名 : Collection集合 & 数组 ) { }//增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器 高级for循环和传统for循环的区别: 高级for循环在使用时,必须要明确被遍历的目标.这个目标,可以是Collection集合或者数组,如果遍历Collec