------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
 
 
Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。
 
 
反射(Reflection)其实就是动态加载一个指定的类,并获取该类中的所有的内容,而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员,简单说
反射技术可以对一个类进行解剖
 
 
反射大大的增强了程序的扩展性
 
 
Java 反射机制主要提供了以下功能:
 
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
 
 

反射的基本步骤:

1、获得Class对象,就是获取到指定的名称的字节码文件对象

2、实例化对象,获得类的属性、方法或构造函数

3、访问属性、调用方法、调用构造函数创建对象

class类:

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

Class和class区别:

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

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

获取Class对象,有三种方式:

1、通过每个对象都具备的方法getClass来获取,弊端:必须要创建该类对象,才可以调用getClass方法

2、每一个数据类型(基本数据类型和引用数据类型)都有一个静态的属性class,弊端:必须要先明确该类

前两种方式不利于程序的扩展,因为都需要在程序使用具体的类来完成

3、使用的Class类中的方法,静态的forName方法

指定什么类名,就获取什么类字节码文件对象,这种方式的扩展性最强,只要将类名的字符串传入即可

     //根据给定的类名来获得  用于类加载
String classname ="cn.itcast.reflect.Person";// 来自配置文件
Class clazz =Class.forName(classname);// 此对象代表Person.class
//如果拿到了对象,不知道是什么类型 用于获得对象的类型
Object obj = new Person();
Class clazz1 =obj.getClass();// 获得对象具体的类型
//如果是明确地获得某个类的Class对象 主要用于传参
Class clazz2 = Person.class;
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
Class类:代表一个类。
Field 类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。
Constructor 类:代表类的构造方法。
Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

Class类中常用的方法:

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

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

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

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

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

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

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

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

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

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

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

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

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代表某个类的一个构造方法。

Constructor构造方法

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

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

创建实例对象

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

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

   注:

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

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

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

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类代表某个类中一个成员变量

 

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表示的字段的值。

 
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;
}
}
//获取Person对象的成员变量
public static void getPersonField() throws Exception{
//如果想要给该变量赋值,必须先要有对象。
Class clazz = Class.forName("cn.itheima.Person");
Person p = (Person)clazz.newInstance();
//获取所有的成员变量
Field[] fs = clazz.getFields();
for(Field f:fs){
System.out.println(f);
}
//获取指定的成员变量
Field fage = clazz.getField("age");
Field fname = clazz.getDeclaredField("name");
//显示改变后的值
fage.set(p, 20);
System.out.println(fage.get(p));
//暴力访问私有变量
fname.setAccessible(true);
fname.set(p, "zhangsan");
System.out.println(fname.get(p));
}

Method类
             
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对象对应的是一个静态方法

 
 
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);
}

数组的反射
 

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

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

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

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

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

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

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

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

 
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayReflect {
public static void main(String[] args) {
int [] a1 = new int[]{1,2,3};
int[][] a2 = new int[2][3];
String [] a3 = new String[]{"a","b","c"};
Object obj1 = a1;
Object obj2 = a3;
Object obj3 = a4;
//Array工具类用于完成对数组的反射操作。如打印任意数值
printObject(a1);
printObject(a4);
printObject("abc");
}
//打印任意数值
private static void printObject(Object obj) {
Class clazz = obj.getClass();
//如果传入的是数组,则遍历
if(clazz.isArray()){
int len = Array.getLength(obj);//Array工具类获取数组长度方法
for(int x = 0;x<len;x++){
System.out.println(Array.get(obj, x));//Array工具获取数组元素
}
}
else
System.out.println(obj);
}
}


 
 
反射的作用——实现框架功能
 
框架:通过反射调用Java类的一种方式。框架如同地产商建造房子,门窗和空调等等内部装修都由用户自己安装。房子就是框架,用户需使用此框架,安好门窗等放入到房地产商提供的框架中。框架和工具类的区别在于工具类被用户类调用,而框架是调用用户提供的类。

框架要解决的核心问题

   我们在写框架的时候,调用的类还未出现,那么框架无法知道要被调用的类名,所以在程序中无法直接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、执行程序主体功能

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

黑马程序员——JAVA基础之反射的更多相关文章

  1. 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)

    正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G  QQ 1481135711 这是我总 ...

  2. 黑马程序员_Java基础:反射机制(Reflection)总结

    ------- android培训.java培训.期待与您交流! ---------- 反射在java中有非常重大的意义,它是一种动态的相关机制,可以于运行时加载.探知.使用编译期间完全未知的clas ...

  3. 黑马程序员----java基础笔记中(毕向东)

    <p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...

  4. 黑马程序员----java基础笔记上(毕向东)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 笔记一共记录了毕向东的java基础的25天课程,分上.中.下 本片为上篇,涵盖前10天课程 1. ...

  5. 黑马程序员——JAVA基础之泛型和通配符

    ------- android培训.java培训.期待与您交流! ---------- 泛型:            JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...

  6. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  7. 黑马程序员——JAVA基础之语法、命名规则

    ------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...

  8. 黑马程序员——JAVA基础之File类,递归,打印流,合并切割流

    ------- android培训.java培训.期待与您交流! ---------- File类 用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递 ...

  9. 黑马程序员——JAVA基础之多线程的安全问题

    ------- android培训.java培训.期待与您交流! ---------- 导致多线程出现问题的一个特殊的状态:就绪.具备了执行资格,但是还没有获取资源. 导致安全问题的出现的原因: 1. ...

随机推荐

  1. PBcR - 纠错及组装算法

    单分子测序reads(PB)的混合纠错和denovo组装 我们广泛使用的PBcR的原始文章就是这一篇 原文链接:Hybrid error correction and de novo assembly ...

  2. android应用锁之监听应用前后台切换方式

    今天在做技术总结,顺便就把知识共享,个人崇尚分享. 通过以下方式来监听是不是发生了应用的前后台切换: 1. android api 10 – 15 通过ActivityManager register ...

  3. 0030 Linux 网络操作命令

    1. 主机是否可达 ping IP 2. 服务是否在运行 telnet IP port 3. 网络配置 ifconfig ip route arp 4. 网络访问 curl wget 5. 网络追踪 ...

  4. 51nod 1134 最长递增子序列

    题目链接:51nod 1134 最长递增子序列 #include<cstdio> #include<cstring> #include<algorithm> usi ...

  5. 最短路径——Floyd算法

    如何求一张图中任意两顶点之间的最短路径长度,这里写一种最简单的算法——Floyd算法: #include<stdio.h> #define inf 9999 int main() { ][ ...

  6. GDI+一般性错误(A generic error occurred in GDI+)

    1.GDI+的前世今生 GDI+全称图形设备接口,Graphics Device Interface (GDI) ,他的爸爸叫做GDI, 用C写的.Windows XP出来以后用C++重新写了一下,变 ...

  7. [转]不正当使用HashMap导致cpu 100%的问题追究

    以前项目中遇到类似业务,但使用的是CurrentHashMap,看到这篇文章,转载记录,警示自己. 以下内容转自: 转载自并发编程网 – ifeve.com(http://ifeve.com/hash ...

  8. C#多线程 线程池

    实例1:直接看看微软提供的代码 using System; using System.Threading; public class Example { public static void Main ...

  9. [强连通分量] POJ 1236 Network of Schools

    Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16803   Accepted: 66 ...

  10. 通过MD5排除重复文件

    今天下载了好多美女图片壁纸,可是看了一下发现好多图片重复了,有强迫症的我必须把重复的都给剔除掉,首先想到的当然是百度了,问问度娘有没有什么图片去重的工具,搜了一下还真有.奈何本人智商捉急用不来这高级的 ...