标签:style blog ar io color os 使用 sp for
一、反射的基础返回字节码,返回的方式有两种:1.这份字节码曾经被加载过,已经存在jvm中,那么就可以直接返回。2.jvm中没有,用类加载器去加载,加载后,字节码缓存到jvm中,以后再这份字节码就不需要加载了。
得到一个类的字节码有三种方法:
1.String.class
2.Person p = new Person(); p.getClass();对象.class
3.Class.forName("java.lang.String");
<span style="white-space:pre"> </span>public static void main(String[] args)throws Exception {
String str1 = "abc";
Class class1 = str1.getClass();
Class class2 = String.class;
Class class3 = Class.forName("java.lang.String");
System.out.println(class1==class2);
System.out.println(class2==class3);
System.out.println(class1.isPrimitive());//是否是原始类型,false,它是类
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class==Integer.class);//false
System.out.println(int.class==Integer.TYPE);//true
System.out.println(int[].class.isArray());//true
}
一个java类中用一个Class类的对象来表示,一个类的组成成分:构造函数,方法,成员变量,包等也同java类来表示,车本身是一个类,它的轮胎、发动机等等也是一个个类。java的Class类提供一系列方法来获得构造函数、方法、成员变量等信息,这些信息就是相应类的实例对象,Field、Method、Contructor、Package等。
一个类中的每个成员都有可以用相应的反射API类的一个实例对象来表示
System.exit(0);
System.gc();
System是一个类
exit、gc也是一个类
Method method1 代表exit()
method2 代表gc()
他们都属于Method类
这也就可以很好的理解java的核心思想:万物皆对象。不论是什么,都是对象
三、反射的应用
1.构造方法
Constructor类代表某个类中的一个构造方法
得到类的所有构造方法: Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到类的一个构造方法: Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
也可以是:Constructor constructor = String.class.getConstructor(StringBuffer.class);
在获得实例对象的时候要注意,指定实例对象的类型,因为编译器只知道是个对象,但是不知道是什么类型的对象String str = (String) constructor.newInstance(new StringBuffer("abc"));
2.成员变量
Field类代表某个类中的一个成员变量
注意fiedx代表的是x的定义,而不是具体的x变量,要想得到x的变量,就必须从对象上获取
public class Reflection {
private int x;
public int y;
public Reflection(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
import java.lang.reflect.Field;
public class LreanReflect {
public static void main(String[] args)throws Exception{
Reflection re = new Reflection(3, 4);
Field fieldy = re.getClass().getField("y");
//fieldy是多少?4?错,fieldy不是对象身上的变量,而是类上,要用它取某个对象上的值
int st = (Integer)fieldy.get(re);
System.out.println(st);
//x是私有的
Field fieldx = re.getClass().getDeclaredField("x");//允许你看见,但是不让你用
fieldx.setAccessible(true);//暴力反射,不管它同不同意,我都要用
st = (Integer)fieldx.get(re);
System.out.println(st);
}
}
import java.lang.reflect.Field;
public class LreanReflect {
public static void main(String[] args) throws Exception {
Reflection reflection = new Reflection(3, 4);
ChangeStringValue(reflection);
System.out.println(reflection);
}
private static void ChangeStringValue(Object obj) throws Exception{
Field[] fields = obj.getClass().getFields();
for(Field f : fields){
//if(f.getType().equals(String.class))//因为只有一份String的字节码
if(f.getType()==String.class){
String str = (String)f.get(obj);
//String value = str.replaceAll("b", "a");
String value = str.replace('b', 'a');
f.set(obj,value);//将更改后的值更新给Reflection
}
}
}
}
package ReflectLearn;
public class Reflection {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "mail";
public Reflection(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString(){
return str1+":"+str2+":"+str3;
}
}
(1)调用方法
Method method = String.class.getMethod("charAt", int.class);
String str1 = "abc";
System.out.println(method.invoke(str1, 1));//invoke,调用
//如果xxx.invoke(null,1)第一参数是null,那么这个方法肯定是静态的,因为不需要对象
import java.lang.reflect.Method;
public class LreanReflect {
public static void main(String[] args) throws Exception {
//MyMain.main(new String[]{"11","22","33"});
String startingClassName = args[0];//这里需要设置一下main参数,因为我不知道要运行那个main方法
//run as ->run Configurations->Arguments(ReflectLearn.MyMain)
System.out.println(startingClassName);
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"11","22","33"}});//打包
//mainMethod.invoke(null, (Object)new String[]{"11","22","33"});
//为什么要打包?main方法接受一个参数(字符串数组),我们传递给它一个字符串数组
//在JDK1.5一个数组就是对应一个参数,但是在JDK1.4,数组中的每一个元素对应一个参数
//我们传递一个String[],也就是一个Object数组,一打开,其中的每个元素都是一个参数,它就会认为收到3各参数
//所以,用Object数组,再打一个包,这样,我给你一包东西,打开后,是一个数组,这样就OK了
//正式因为,要拆开,所以我提前就给你打一个包
}
}
class MyMain{
public static void main(String[] args){
for(String s : args){
System.out.println(s);
}
}
}
import java.lang.reflect.Array;
import java.util.Arrays;
public class LreanReflect {
public static void main(String[] args) throws Exception {
int[] arr1 = new int[3];
int[] arr2 = new int[4];
int[][] arr3 = new int[3][4];
String[] arr4 = new String[]{"a","b","c"};
System.out.println(arr1.getClass() == arr2.getClass());
System.out.println(arr1.getClass().getName());
System.out.println(arr1.getClass().getSuperclass().getName());
Object obj1 = arr1;
//Object[] obj2 = arr2;这样不行
Object[] obj3 = arr3;
Object obj4 = arr4;
Object[] obj5 = arr4;
System.out.println(Arrays.asList(arr1));
System.out.println(Arrays.asList(arr4));//字符串可以
printElement(arr1);
}
private static void printElement(Object arr1) {
Class c = arr1.getClass();
if(c.isArray()){
int len = Array.getLength(arr1);
for(int i = 0;i<len;i++){
System.out.println(Array.get(arr1,i));
}
}else{
System.out.println(arr1);
}
}
}
public class Reflection {
private int x;
public int y;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Reflection other = (Reflection) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
public Reflection(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
public class ReflectTest2 {
public static void main(String[] args) {
Collection conCollection = new HashSet();
Reflection[] rs = new Reflection[]{
new Reflection(3, 3),new Reflection(4, 4),new Reflection(3, 3)
};
for(Reflection r : rs)
conCollection.add(r);
//rs[0].y = 1;
System.out.println(conCollection.contains(rs[0]));
boolean b = conCollection.remove(rs[0]);
System.out.println(b);
System.out.println(conCollection.size());
}
}
true
true
1
把注释打开
false
false
2
config.properties
className=java.util.ArrayList
public class Reflection {
private int x;
public int y;
public Reflection(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
public class ReflectTest2 {
public static void main(String[] args) throws Exception {
InputStream in = new FileInputStream("D:/JavaSourue/config.properties");
Properties pro = new Properties();//从配置文件中,得到是什么类
pro.load(in);
in.close();
String className = pro.getProperty("className");
Collection conCollection = (Collection)Class.forName(className).newInstance();
Reflection[] rs = new Reflection[]{
new Reflection(3, 3),new Reflection(4, 4),new Reflection(3, 3)
};
for(Reflection r : rs)
conCollection.add(r);
System.out.println(conCollection.size());
}
}
因为在写框架时,无处得知以后要调用什么类,也就无法new对象,所以就必须用反射来解决这个问题
标签:style blog ar io color os 使用 sp for
原文地址:http://blog.csdn.net/wjw0130/article/details/42007367