一、理解Class类
1、java程序中的各个java类属于一类事物,描述这类事物的java类名就叫做Class
2、Class类代表java类,而他的各个对象代表各个类在内存中的字节码。一个类被类加载器加载到内存中,占用内存一片空间,这个空间里的内容就是类的字节码。不同类的字节码是不同的。所以他们在内存里的内容是不同的。这一个个空间分别用一个个对象来表示,这里的对象就是Class类的对象
3、如何得到Class类型(类的字节码)
类名.class,例如,System.class
对象.getClass(),例如,new Date().getClass()
Class.forName("类名"),例如,Class.forName("java.util.Date");
Point point = new Point();
Class clazz1 = point.getClass();
Class clazz2 = Point.class;
Class clazz3 = Class.forName("test.java.com.day1.Point");
System.out.println(clazz1==clazz2);//输出true
System.out.println(clazz1==clazz3);//输出true
例1、判断是不是数组
String[] a= new String[]{"1","2","3"};
if(a.getClass().isArray()){
System.out.println(Arrays.asList(a));
}
二、反射
1、什么是反射
反射就是将java类中的各个成分映射成相应的java类
例如,一个java程序中的java类用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
2、Constructor类
Constructor类代表某个类中的一个构造方法
//得到某个类的所有构造方法
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
//得到某个构造方法
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuilder.class);
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));
//调用获得的方法时要用到上面相同类型的实例对象
Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。
3、Field类代表某个类中的一个成员变量
class Point{
private int pointx=0;
private int pointy=1;
}
Field fieldx = Point.class.getField("pointx");
System.out.println(fieldx.get(new Point()));
Field fieldy = Point.class.getDeclaredField("pointy");
fieldy.setAccessible(true);
System.out.println(fieldy.get(new Point()));
/**
* 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"。
* @author chenweisong
*
*/
class Stringreplace{
private String a = "abstract";
public String b = "aabbcccbf";
int c=2;
public String toString(){
System.out.println(a+"\r\n"+b+"\r\n"+c);
return null;
}
public void replaceAll() throws Exception{
Field[] fields = Stringreplace.class.getDeclaredFields();
for(Field field:fields){
field.setAccessible(true);
if(field.getType()==java.lang.String.class){
String str = (String)field.get(this);
field.set(this, str.replace("b", "a"));
}
}
System.out.println(this);
}
}
4、Method类代表某个类中的一个成员方法
//得到一个类的方法
Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
String str = "abc";
System.out.println(str.charAt(1));
System.out.println(charAt.invoke(str, 1));
5、数组的反射
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。