1,构造方法的反射
package javaBase.reflect;
import java.lang.reflect.Constructor;
/*
* 三种获取字节码对应的实例对象(Class类型)的方法:
* 九种预定义的 Class 对象,表示八个基本类型和 void
* boolean、byte、char、short、int、long、float、 double。
* 源程序中出现的类型,都有各自的Class实例对象:int[] ,void .....
*/
public class Test1 {
public static void main(String[] args) throws Exception{
String str1 = "haha";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");//详细
System.out.println(cls1 == cls2);//true
System.out.println(cls1 == cls3);//true
//判断一个类是不是基本数据类型:
System.out.println(cls1.isPrimitive());//false
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class==Integer.class);//Integer是包装类,false
System.out.println(int.class == Integer.TYPE);//type:包装的源数据类型 true
System.out.println(int[].class.isPrimitive());//数组也是一个类型,不是原始类型
System.out.println(int[].class.isArray());
//Constructor类代表某个类中的一个构造方法
Constructor c1 = String.class.getConstructor(StringBuffer.class);
// 用反射实现:String s1 = new String(new StringBuffer("abc"));
String str2 = (String)c1.newInstance(new StringBuffer("abc"));
//编译时:不会执行等号赋值,只检查语法,看定义,所以不知道c1是个什么对象的构造方法
System.out.println(str2.charAt(2));
}
//反射就是将java类中的各种成分映射成相应的java类
}
2,成员变量的反射
package javaBase.reflect;
//反射就是将java类中的各种成分映射成相应的java类
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
* 三种获取字节码对应的实例对象(Class类型)的方法:
* 九种预定义的 Class 对象,表示八个基本类型和 void
* boolean、byte、char、short、int、long、float、 double。
* 源程序中出现的类型,都有各自的Class实例对象:int[] ,void .....
*/
public class Test1 {
public static void main(String[] args) throws Exception{
String str1 = "haha";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");//详细
System.out.println(cls1 == cls2);//true
System.out.println(cls1 == cls3);//true
//判断一个类是不是基本数据类型:
System.out.println(cls1.isPrimitive());//false
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class==Integer.class);//Integer是包装类,false
System.out.println(int.class == Integer.TYPE);//type:包装的源数据类型 true
System.out.println(int[].class.isPrimitive());//数组也是一个类型,不是原始类型
System.out.println(int[].class.isArray());
//Constructor类代表某个类中的一个构造方法
Constructor c1 = String.class.getConstructor(StringBuffer.class);
// 用反射实现:String s1 = new String(new StringBuffer("abc"));
String str2 = (String)c1.newInstance(new StringBuffer("abc"));
//编译时:不会执行等号赋值,只检查语法,看定义,所以不知道c1是个什么对象的构造方法
System.out.println(str2.charAt(2));
Point p = new Point(3, 5);
//fieldY是类的,不是具体对象的。用它去取某个具体对象上对应的值
Field fieldY = p.getClass().getField("y");//y是类的字段名
System.out.println(fieldY.get(p));
// Field fieldX = p.getClass().getField("x");//找不到,x是private
Field fieldX = p.getClass().getDeclaredField("x");//可以看见了,但是不能取
fieldX.setAccessible(true);//暴力反射
System.out.println(fieldX.get(p));
changeStringValue(p);
System.out.println(p);
}
/*
* 将一个对象中的String类型成员变量的值中“b”改成“a”
*/
private static void changeStringValue(Point p) throws Exception {
Field[] fields = p.getClass().getFields();
for(Field f:fields){
if(f.getType()==String.class){//字节码只有一份,用==比较,而不用equals()
String oldValue = (String)f.get(p);//获取成员变量值
String newValue = oldValue.replace("b", "a");
f.set(p, newValue);//成员变量重新赋值
}
}
}
}
附:Point类
package javaBase.reflect;
public class Point {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "bascketball";
public String str3 = "it";
public Point(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return str1+": "+str2+": "+ str3;
}
}
3成员方法的反射
//Method 例子:charAt()
Method mCharAt = String.class.getMethod("charAt", int.class);
char ch = (Character)mCharAt.invoke(str1, 1);//invoke调用.str1这里为null是静态方法
System.out.println(ch);
4,main()方法反射
<span style="white-space:pre"> </span>new DoMain().main(new String[]{"111","222","333"});
//main()方法,不知道类的名字,只知道到时候传过来要调用其main方法
String someClassName = args[0];//传入类名(带包)
Method mainMethod =
Class.forName(someClassName).getMethod("main", String[].class);
mainMethod.invoke(null, (Object)new String[]{"111","222","333"});//静态方法用null
/*
* jdk1.4把数组当成n个参数,jdk1.5把数组当做一个参数,为了兼容1.4:
* java5会自动把数组弄成多个单独参数
* 这两种方法都可以避免数组被拆成几个参数
*/
mainMethod.invoke(null, new Object []{new String[]{"111","222","333"}});
5,数组的反射
package javaBase.reflect;
import java.lang.reflect.Array;
/*
* 数组的反射
*/
public class ArrayReflect {
public static void main(String[] args) {
int[] a1 = new int[3];
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] s = new String[3];
System.out.println(int.class.getSuperclass());//null,基本类型没有父类?
System.out.println(a1.getClass()==a2.getClass());//true维度,类型相同
// System.out.println(a1.getClass() == a3.getClass());
// System.out.println(a1.getClass() == s.getClass());
System.out.println(a1.getClass().getName());//类名:[I
System.out.println(a1.getClass().getSuperclass().getName());//obj
System.out.println(a3.getClass().getName());//[[I
System.out.println(s.getClass().getSuperclass().getName());//obj
Object o1 = a1;
Object o2 = a3;
Object o3 = s;
// Object[] o4 = a1;//基本数据类型数组不是Object[];整个数组是一个Object对象
Object[] o5 = s;
Object[] o6 = a3;//降低了维度
String[] strings = new String[]{"a","b","c"};
printObj(strings);
printObj("haha");
}
/*
* 数组的反射类:Array
*/
private static void printObj(Object obj) {
Class clazz = obj.getClass();
if(clazz.isArray()){
int len = Array.getLength(obj);//得到数组长度
for(int i=0;i<len;i++){
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}
}
6,反射与框架,通过配置文件创建对象
package javaBase.reflect;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
/*
* 当一个对象存储到hashset中后,就不要修改那些参与计算哈希值的字段了
* 否则修改后的对象hashcode值与存入时不同,导致不能找到这个对象和单独删除该对象导致内存泄露
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
InputStream in = new FileInputStream("config.properties");
Properties prop = new Properties();
prop.load(in);
in.close();//关闭资源:当前操作系统的窗口或者什么为其提供资源的对象
//用反射建立集合
String className = prop.getProperty("className");
Collection c = (Collection)Class.forName(className).newInstance();
// Collection c = new HashSet();
Point p1 = new Point(3, 3);
Point p2 = new Point(5, 5);
Point p3 = new Point(3, 3);
c.add(p1);
c.add(p2);
c.add(p3);
c.add(p1);
// p1.y = 7;
c.remove(p1);//上面这句执行后会导致remove()找不到p1,从而不能删除
System.out.println(c.size());
}
}