一.概念
反射就是把Java的各种成分映射成相应的Java类。
反射就是把Java的各种成分映射成相应的Java类。
Class类的构造方法是private,由JVM创建。
得到字节码的三种方法:
//1.类名
Class c1 = Date.class();
//2.对象
Person p1 = new Person();
p1.getClass();
//3.类名字符串(包名+类名)。若存在则加载,否则新建,往往使用第三种,类的名字在写源程序时不需要知道,到运行时再传递过来
Class.forName("java.lang.String");
例子:
package com.tx;
import java.lang.reflect.*;
class test {
int a;
void aa(int i){
}
static void bb(double i){
}
}
public class hw {
public static void main(String args[]) {
try {
System.out.println(String.class.getConstructor(StringBuffer.class));
System.out.println("The name of class testtt is: "+test.class.getName());
test tt = new test();
System.out.println("The class of " + tt + " is " + tt.getClass().getName());
Class c = Class.forName("com.tx.test");
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e){
System.err.println(e);
}
}
}
public java.lang.String(java.lang.StringBuffer)
The name of class testtt is: com.tx.test
The class of com.tx.test@55f33675 is com.tx.test
static void com.tx.test.bb(double)
void com.tx.test.aa(int)
二.常用方法
1. newInstance方法相当于调用类的默认的构造器
Class cls1 = Role.class;
Object o = cls1.newInstance();
Object o1 = new Role(); //与上面的方法等价
2. isPrimitive判断是否是基本类型的字节码
Class cls1 = str.getClass();
System.out.println(cls1.isPrimitive()); //true
3. Filed类代表某一类中的一个成员变量。
import java.lang.reflect.Field;
public class TestReflect {
public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
ReflectPointer rp1 = new ReflectPointer(3,4);
Field fieldx = rp1.getClass().getField("x");//必须是x或者y
System.out.println(fieldx.get(rp1));
/*
* private的成员变量必须使用getDeclaredField,并setAccessible(true),否则看得到拿不到
*/
Field fieldy = rp1.getClass().getDeclaredField("y");
fieldy.setAccessible(true);//暴力反射
System.out.println(fieldy.get(rp1));
}
}
class ReflectPointer {
public int x = 0;
private int y = 0;
public ReflectPointer(int x,int y) {//alt + shift +s相当于右键source
super();
// TODO Auto-generated constructor stub
this.x = x;
this.y = y;
}
}
package com.tx;
import java.lang.reflect.Field;
public class hw {
public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
ReflectPointer rp1 = new ReflectPointer(3,4);
changeBtoA(rp1);<span style="white-space:pre"> //所有值改为*
System.out.println(rp1);
}
private static void changeBtoA(Object obj) throws RuntimeException, Exception {
Field[] fields = obj.getClass().getFields();
for(Field field : fields) {
//if(field.getType().equals(String.class))
//由于字节码只有一份,用equals语义不准确
if(field.getType()==String.class) {
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b', '*');
field.set(obj,newValue);
}
}
}
}
class ReflectPointer {
private int x = 0;
public int y = 0;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcat";
public ReflectPointer(int x,int y) {//alt + shift +s相当于右键source
super();
// TODO Auto-generated constructor stub
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "ReflectPointer [str1=" + str1 + ", str2=" + str2 + ", str3="
+ str3 + "]";
}
}
package com.tx;
import java.lang.Class;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;<strong>
</strong>public class hw {
public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
//获取整个类
Class c1 = Class.forName("java.lang.Integer");
//获取所有的属性?
Field[] fs = c1.getDeclaredFields();
//定义可变长的字符串,用来存储属性
StringBuffer sb = new StringBuffer();
//通过追加的方法,将每个属性拼接到此字符串中
//最外边的public定义
sb.append(Modifier.toString(c1.getModifiers()) + " class " + c1.getSimpleName() +"{\n");
//里边的每一个属性
for(Field field:fs){
sb.append("\t");//空格
sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字
sb.append(field.getName()+";\n");//属性的名字+回车
}
sb.append("}");
System.out.println(sb);
}
}
public final class Integer{
public static final int MIN_VALUE;
public static final int MAX_VALUE;
public static final Class TYPE;
static final char[] digits;
static final char[] DigitTens;
static final char[] DigitOnes;
static final int[] sizeTable;
private static String integerCacheHighPropValue;
private final int value;
public static final int SIZE;
private static final long serialVersionUID;
}
4. 方法调用
package com.tx;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class hw{
public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
// String str = args[0];
/*
* 这样会数组角标越界,因为压根没有这个字符数组
* 需要右键在run as-configurations-arguments里输入b.Inter(完整类名)
*
*/
Method m = Class.forName("com.tx.Inter").getMethod("main1",String[].class);
//下面这两种方式都可以,main方法需要一个参数
m.invoke(null, new Object[]{new String[]{"111","222","333"}});
m.invoke(null, (Object)new String[]{"6111","6222","6333"});//这个可以说明,数组也是Object
/*
* m.invoke(null, new String[]{"111","222","333"})
* 上面的不可以,因为java会自动拆包
*/
}
}
class Inter {
public static void main1(String[] args) {
for(Object obj : args) {
System.out.println(obj);
}
}
}
111
222
333
6111
6222
6333
package com.tx;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class hw {
public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
String str = "sh8sfs";
Method mtCharAt = String.class.getMethod("charAt", int.class);
Object ch = mtCharAt.invoke(str,1);//若第一个参数是null,则肯定是静态方法
System.out.println(ch);
System.out.println(mtCharAt.invoke(str, new Object[]{2}));
}
}
h
8
5. isInstance操作符
class S {
}
public class IsInstance {
public static void main(String args[]) {
try {
Class cls = Class.forName("S");
boolean b1 = cls.isInstance(new Integer(37));
System.out.println(b1);
boolean b2 = cls.isInstance(new S());
System.out.println(b2);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
创建一个S 类的 Class 对象,然后检查一些对象是否是S的实例。Integer(37) 不是,但 new S()是。
6. 数组
int.class和Integer.class不是同一份字节码,Integer.TYPE,TYPE代表包装类对应的基本类的字节码 int.class==Integer.TYPE
import java.util.Arrays;
/*
* 从这个例子看出即便字节码相同但是对象也不一定相同,根本不是一回事
*
*/
public class TestReflect {
public static void main(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception {
int[] a = new int[3];
int[] b = new int[]{4,5,5};//直接赋值后不可以指定长度,否则CE
int[][] c = new int[3][2];
String[] d = new String[]{"jjj","kkkk"};
System.out.println(a==b);//false
System.out.println(a.getClass()==b.getClass());//true
//System.out.println(a.getClass()==d.getClass()); //比较字节码a和cd也没法比
System.out.println(a.getClass());//输出class [I
System.out.println(a.getClass().getName());//输出[I,中括号表示数组,I表示整数
System.out.println(a.getClass().getSuperclass());//输出class java.lang.Object
System.out.println(d.getClass().getSuperclass());//输出class java.lang.Object
//由于父类都是Object,下面都是可以的
Object obj1 = a;//不可是Object[]
Object obj2 = b;
Object[] obj3 = c;//基本类型的一位数组只可以当做Object,非得还可以当做Object[]
Object obj4 = d;
//注意asList处理int[]和String[]的区别
System.out.println(Arrays.asList(b));//1.4没有可变参数,使用的是数组,[[I@1bc4459]
System.out.println(Arrays.asList(d));//[jjj, kkkk]
}
}
7. 其他
对于泛型,只是允许程序员在编译时检测到非法的类型而已。
但是在运行期时,其中的泛型标志会变化为 Object 类型。
List<Integer> list = new ArrayList<Integer>();
list.add(12);
//这里直接添加会报错
//add.invoke(list, "test");
Class<? extends List> clazz = list.getClass();
Method add = clazz.getDeclaredMethod("add", Object.class);
//但是通过反射添加,是可以的
add.invoke(list, "test")
System.out.println(list);