黑马程序--Java之反射05

黑马程序–Java之反射05

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

一、反射的基石类——Class类

  众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。
 Java程序中的各个Java类拥有共同的特性,属于同一类事物,Class类就是用来描述这类事物的Java类。Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、Java基本类型(boolean, byte,char, short, int, long, float, double)以及关键词void。
  当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码”来观察Class 对象的实际生成时机(例如在Class的构造方法内添加一个println()),这样是行不通的!因为Class并没有公有的 构造方法。一个Class类表示一个特定类的属性。

class Demo{
    ...
}
    Demo d1 = new Demo();
    Demo d2 = new Demo();
    Class c1=d1.getClass();
    String name1 = d1.getClass().getName()
    Class c2=Demo.class;   //用某一个类的字节码赋值
    String name2 = c2.getName();   
    Class.forName("java.lang.String");//参数是类的路径的字符串,返回这个类的字节码

  所有的类都有相应的Class对象,有九个预定义的Class对象,8个基本类型和一个void:

Class i= int.class; 
Class v=void.class;
boolean flag= i.isPrimitive() //判断一个Class类是否是基本数据类型。 
i.class==Interger.TYPE //Interger.TYPE 返回包装类型的字节码 
System.out.println(int[].class.isPrimitive()); //返回false,数组不是原始类型 
System.out.println(int[].class.isArray()); //判断一个Class类对象是否是数组

二、什么是反射?

  反射就是把Java类中的各种成分映射成相应的Java类。例如,一个Java类中用一个Class类的对象来表示,一个类的组成部分:成员变量,构造方法,方法,包等等信息也用一个个Java类来表示,就像汽车是一个类,那么汽车的发动机,邮箱也分别是一个个的类。表示Java类的Class类显然要提供一系列的方法,来获得其中的变量,构造方法,方法,包等信息,这些信息应该用相应类的实例来表示,他们分别是Field,Contrutor, Method, Package等等。
  通过Class类的方法可以返回一个类的所有成员的相对应的实例对象,得到这些实例对象的作用和使用方法如:

Field getField (String name); 
Method getMethod(String name); 
Package getPackage(String Package); //返回成员变量相对应的类的对象

2.1、构造方法反射的应用

//得到某一个类的所有构造方法, 
Constructor [] constructors = Class.forName("java.lang.String").getConstructors();
//返回一个包含某些Constructor 对象的数组,
//这些对象反映此 Class 对象所表示的类的所有公共构造方法。 
//得到某一个构造方法 
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class/*,int.class*/);
Class.getConstructor(StringBuffer.class...)
//根据传入的参数类型和个数不同返回相应的构造方法
//用构造方法的实例创造类的实例 
String str= new String(new StringBuffer("abc")); 
Constructor constructor = Class.String.getConstructor(StringBuffer.class); 
String str2 = (String)constructor.newInstance(new StringBuffer("abc"));
//返回一个实例对象,编写程序时并不知道constructor是哪个类的构造方法,
//只有在程序运行时根据实际传入的参数来得到相应的构造方法再创建Object对象,此时需使用强制类型转换。

  Class.newInstance()方法使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。例如:String str=(String) Class.String. newInstance() //调用无参数的默认构造方法构造实例。

2.2、成员变量反射的应用

  通过field的对象变量去取对象的成员变量

ReflectPiont pt1 = new ReflectPiont();//ReflectPiont()有两个成员变量x和y,其中x为私有变量;
Filed fieldY = pt1.getClass().getField("y");
Filed fieldX = pt1.getClass().getDeclaredField("x");
/* 返回一个Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。*/
System.out.println(fieldY.get(pt1));
/*fieldX,fieldY不是对象身上的属性,而是该类的属性,要用该属性去取得对象的属性值;这个方法不能得到私有的成员变量*/
f2.setAccessible(true);
//为了访问私有成员变量,设置对象 accessible标志的为true;
System.out.println(fieldX.get(pt1));

2.3、成员方法反射的应用

  Method 类代表某个类的一个成员方法

//得到类中的某一个方法 
Method methodCharAt = String.class.getMethod("charAt",int.class);
//第一个参数方法名,后面的参数是成员变量的参数类型;
//调用方法 
str.charAt(1); 
char c = methodCharAt.invoke(str1,1); 
char c = methodCharAt.invoke(null,1); 
//第一个参数为null,则调用的是静态方法

  jdk1.4和jdk1.5的invoke()的区别
  jdk1.5有了可变参数,如果调用的方法有多个参数,不需要传入数组

2.4数组的反射

  具有相同元素类型和相同维度的数组属于同一个类,拥有相同的字节码。

int[]  a1 = new int [3]; 
int[]  a2 = new int[4]; 
int[][]  a3 = new int[3][4]; 
String[]  s1 = new String[3]; 
a1.getClass() == a2.getClass();//返回true 
a1.getClass() == a3.getClass(); 
//false或者编译无法通过(我的实践结果是无法通过编译,MyEclipse报错) 
a1.getClass() == s1.getClass(); 
/*false 或者编译无法通过(我的实践结果是无法通过编译,MyEclipse报错)*/
//代表数组的Class实例对象的getSuperclass()方法,返回的父类为Object类对应的Class 
String str1=a1.getClass().getSuperclass().getName(); 
String str2=s1.getClass().getSuperclass().getName(); 
//他们的父类都是Object,str1==str2

  基本数据类型的一维数组可以被当做Objet类型使用,但不能当做Object[]类型使用,非基本类型的一维数组,既可以当做Object,也可以当做Object[];

Object aObj1=a1; //a1相当于有一个数组,里面存储的是int[] 
Object sObj1=s1; 
Object[] aObj2=a1; //这一行是错误的,基本类型不能当做Object 
Object[] aObj3=a3; //a3是数组的数组,相当于有一个数组,里面存储的是int数组 
Object[] sobj2=s1; //s1相当于,有一个数组,里面存储的是String
/*Arrays.asList()方法处理int[]和String[]时的差异*/                    
int[] a=new int[]{1,2,3};
String[] s=new String[]{'a','b','c'};   
System.out.println(a1);
System.out.println(s1);//打印出来是hashcode的值,不方便看
System.out.println(Arrays.asList(a1));
//转换List只有一个元素,
System.out.println(Arrays.asList(s1));
//成功转换成List,打印出a,b,c

  public static List asList(Object[] a)方法 将一个数组转换成List,但参数是Object[],a1无法转换成Object[],只能当做一个Object,所以打印出来还是Hashcode值

2.5数组反射应用

  Array工具类可以完成对数组的反射操作,是对数组进行反射的类
 反射的做用–框架功能的实现
 ArrayList与HashSet的区别
 ArrayList是一个顺序的数组,按先后顺序存储元素,同一元素而已存放多次;
 HashSet添加一个新的元素,需要先判断是否存在,如果已经存在,则不能添加,或者先删除原来的元素再添加。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值