Java高新技术 ,反射

 


 

Class类
。Class类实例对象对应各个类在内存中的字节码
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字
节码,不同类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间
可分别用一个个的对象来表示,这些对象具有相同的类型Class类型
。获得各个字节码对应的实例对象有三种方法
1)类名.class   System.class
2)对象.getClass()   new Date().getClass()
3)Class.forName("类名")   Class.forName("java.util.Date")
该方法获得字节码两种方式 1 类字节码已经加载到内存中,直接在内存中获得。2 在
虚拟机中还没有该类字节码,需要类加载器加载字节码到内存,再获得字节码。

int.class.isPrimitive() 判断是否是基本数据类型的字节码
int.class.isPrimitive() == Integer.classisPrimitive() 结果为false 因为int为
基本数据类型。这就是9大数据类型预定义  多出的是void.class
int.class.isPrimitive() == Integer.TYPE  结果为true  TYPE字段代表其对应基本
数据类型的字节码
数组类型的Class实例对象  Class.isArray()
总结:只要是源程序中出现的类型,都有各自的Class实例对象 ,例:int[] void 等

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

Constructor  con1 = String.class.getConstruactor(StringBuffer.class);
获取Class的构造方法getConstructor() 传的参数表示获取String具体哪一个构造方法
String str = con1.newInstance(new StringBuffer("abc"));
因为获得了具体的构造方法,那么可以用该构造方法创建一个String对象,
newInstance()就是使用该构造方法,参数为该构造方法应传入的参数。
步骤:先获得字节码---->根据Class获得构造方法(参数确定具体哪个)---->根据
Constructor的newInstance()方法创建对象(因为构造方法确定,要传入上面类型的对象) 

Class类中有newInstance()方法:其实该方法将获得构造方法的部分封装了,该方法
得到默认的构造方法,在用该构造方法创建对象。其实内部有Constructor对象。


Field类                      代表某类中的一个成员变量

 
 

public class ReflectPoint {
 private int x ;
 public int y ;
public String str1 = "ball";
 public String str2 = "baseketball";
 public String str3 = "itcast";
 
 public ReflectPoint(int x, int y) {
  this.x = x;
  this.y = y;
 }
 
 @Override
 public String toString(){
  return str1+".."+str2+"..."+str3;
 } 
}

 

ReflectPoint pt = new ReflectPoint(3,5);
  Field fieldY = pt.getClass().getField("y");

//这里的fieldY是ReflectPoint类中的成员变量y,没有具体的值,它的值要由一个具体对象获得
  System.out.println(fieldY.get(pt));//fieldY.get(pt);就是获得pt这个对象中的y的值

Field fieldX = pt.getDeclaredField("x");

//因为x是private修饰私有的,所以要获得类中的私有变量要用getDeclaredField()方法

fieldX.setAccessible(true);//已经获得类中的x,要去取实例对象x具体值时,需要设置权限,可以获取对象中x的值

System.out.println(fieldY.get(pt));

 

/*对具体对象变量值的改变*/

private static void changStringValue(Object obj)throws Exception {
    Field[] fields = obj.getClass().getFields();//获得类中的所有成员变量
  for(Field field : fields){ //遍历数组
   if(field.getType() == String.class){//判断类中的一个对象是否是String类型的,用==时因为类的字节码在内存中是唯一的
    String oldstr = (String)field.get(obj);//get方法获取某个对象中具体变量的值
    String newstr = oldstr.replace('b', 'a');//将变量的值转变
    field.set(obj, newstr);//将变化完的变量值在设置到该对象中
   }
  }
  System.out.println(obj);//结果是aall..aaseketaall...itcast
  
 }

 


Method类    代表某个类中的一个方法

通常方式:str.charAt(1);
Mehtod methodCharAt = String.class.getMethod("charAt",int.class);
获得类中的一个方法,参数是方法的名称和方法的参数类型
methodCharAt.invoke(str, 1)
已经获得方法,要运行方法就调用该方法对象的运行方法invoke(),参数是运行
methodCharAt方法的对象str和传入方法的int类型的参数1.
如果invoke(null, 1)则说明对应的方法为静态方法

数组的反射

。维数和元素类型相同的数组属于同一类型(具有相同的Class实例对象)
。代表数组的Class实例对象的getSuperclass()方法返回的父类为Object对应的Class
。基本类型的一维数组可以被当做Object类型使用,不可以当做Object[]类型使用
   非基本类型的都可以

。Arrays.asList()方法处理int[]和String[]时的差异。
1.4版本 asList(Object[] obj)     1.5版本 asList(T...a)
因为int[]不可以转换成Object[],所以是1.5版本的方法,接收的是对象,打印哈希码
而String[]可以被当做Object[]类型,所以是1.4版本方法

Array工具类完成对数组的反射操作

 
 

public void printObject(Object obj)
{
 Class class = obj.getClass();
 if(class.isArray())  //通过该方法判断是不是数组
 {
  int len = Array.getLength(obj); //获取obj数组长度
  for(int x=0;x<len; x++)
  {
   System.out.println(Array.get(obj,x));//获取obj数组第x个元素
  }
 }else{
  System.out.println(obj); 
 }
}

ArrayList HashSet比较及HashCode分析
集合存储的元素都是引用,ArrayList元素存储是有顺序的,按存储的前后顺序
HashSet元素是比较是否相同,不能存储相同的元素
HashCode可以解决当向HashSet存储元素时要和其内存在的元素挨个进行比较,HashSet
内存储的元素根据HashCode的不同进行分区域,这样比较时,根据元素HashCode在HashSet
中比较存储。  当HashCode相同时,则用equals方法比较,所以equals相等时,让HashCode
也相等,当元素存储到HashSet中后不能对它的HashCode的定义内容改变,因为该元素的
HashCode会改变,该元素remove不出去,会占用资源,当大量出现时会内存泄漏。

 

 
 

//反射的作用  实现框架功能

//配置文件config.properties内容:classname=java.util.HashSet

 

import java.io.*;
import java.util.*;

public class ReflectTest2 {


 public static void main(String[] args) throws Exception{

  
  InputStream in = new FileInputStream("config.properties");//读取流读取配置文件
  Properties proper = new Properties();//创建集合,该集合可以将读取到的键值对直接存储
  proper.load(in);//将流读取的内容存储到Properties集合中
  in.close();
  String classname = proper.getProperty("classname");//由键获取到对应的值
  Collection collections = (Collection)Class.forName(classname).newInstance();
  //Class.forName() 获取某类类型  newInstance()调用该类型的无参构造方法
  
  ReflectPoint pt1 = new ReflectPoint(3,3);
  ReflectPoint pt2 = new ReflectPoint(5,5);
  ReflectPoint pt3 = new ReflectPoint(4,3);
  
  //Collection collections = new HashSet();
  collections.add(pt1);
  collections.add(pt2);
  collections.add(pt3);
  
  System.out.println(collections.size());
 }

}

其实配置文件的加载都是用的类加载器

InputStream in = ReflectTest2.class.getClassLoader.getResourceAsStream("config.properties");

该方式是通过类获得类加载器getClassLaoder() 通过类加载器的方法获得配置文件getResourceAsStream()

InputStream in = ReflectTest2.class.getResourceAsStream("config.properties");

该方法直接通过类就由类加载器加载配置文件,其实方法内部有调用getClassLoader()方法



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值