---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ---------------------
Java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class
获取类的字节码的方式(3种):
1、用Class类中的forName()方法:
Eg:
String className=”java.lang.String ”;
Class clazz=Class.forName(className);
2、类名.class eg:Person.class
3、Object类中的getClass()方法(对象.getClass())
使用过程中主要使用第一种
Class中有九个预定义的基本类型的字节码,分别是:byte.class,short.class,int.class,long.class,char.class,float.class,double.class,boolean.class,void.class
可以用Class中的isPrimitive()方法来判断是否是基本类型的字节码,另外
Int.class==Integer.class(输出结果:false)
Int.class==Integer.TYPE(输出结果:true)
还可以判断一份字节码文件是否是数组字节码文件,int[].class.isArray();
反射概念:反射就是把一个java类中的各个成分解析成相应的java类
列如:一个java类包含成员变量、方法、构造方法、包等信息,在Class类中显然提供了一系列的方法来获取这些成员对应的一个实例对象,这些实例对象对应的类分别为Field、Method、Contructor、Package等等
列如:在System类中有两个静态方法,分别是:System.exit()和System.getProperties();那么这两个方法分别为Method类的实例
得到一个类中的所有构造方法:
Constructor[] con1=Class.forName("java.lang.String").getConstructors();
得到一个类中某个构造方法:
Constructor con2=Class.forName("java.lang.String").getConstructor(String.class);
利用反射的方法创建一个String对象:
Constructor con2=Class.forName("java.lang.String").getConstructor(String.class);
String str=(String)con2.newInstance("abc");
关于反射无参构造方法:
Constructor com3=Class.forName("java.lang.String").getConstructor();
String s1=(String) com3.newInstance();
也可以直接:
String s2=(String) Class.forName("java.lang.String").newInstance();
Field类
一个Field类的对象代表了一个类中的一个成员变量
Field类中的知识点:
定义一个Point类,然后在FieldReflect类中对Point类进行反射
Point 类
public class Point {
private int x;
public int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
FieldReflect 类
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class FieldReflect {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class clazz = Class.forName("Point");
Constructor con = clazz.getConstructor(int.class, int.class);
Point point = (Point) con.newInstance(1, 2);
Field field1 = clazz.getField("x");
Field field2 = clazz.getField("y");
int x = (int) field1.get(point);
int y = (int) field2.get(point);
System.out.println(x + " " + y);
}
}
输出结果:
这是因为x是private,所以造成错误,那么有没有办法可以解决呢?
修改如下(field.getDeclaredField(),又叫暴力访问)
Field field1=clazz.getDeclaredField("x");
field1.setAccessible(true);
实例:给出一个对象,将这个对象中的所有是字符串的字段值修改
Original类
package ModifyString;
public class original {
private String str1 = "basketball";
private String str2 = "ball";
private String str3 = "badminton";
public String toString() {
return str1 + " " + str2 + " " + str3;
}
}
ReflectTest 类
package ModifyString;
import java.lang.reflect.Field;
public class ReflectTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Class clazz = Class.forName("ModifyString.original");
Field[] fields = clazz.getDeclaredFields();
original or = (original) clazz.newInstance();
for (Field field : fields) {
field.setAccessible(true);
if (field.getType() == java.lang.String.class) {
String str = (String) field.get(or);
String newstr = str.replace('a', 'b');
field.set(or, newstr);
}
}
System.out.println(or);
}
}
获取指定Class中的方法:(类的方法而不是对象的方法)
String str="abc";
Method method=String.class.getMethod("charAt", int.class);
System.out.println(method.invoke(str, 1));
如果invoke()的第一个参数为null,说明加载的是个静态方法,后面的参数代表传给该方法的参数
现在我想来反射main()方法,那么我们为什么要反射main()方法,它有什么用处呢?
就是我在定义一个类(A类)时,在类中(A类)完全没有说明要调用哪个类(假如要调用B类)中的main()方法,完全是在启动A类时,通过传入的参数来决定的(传入哪个类的类名,就调用哪个类)
package ReflectMain;
import java.lang.reflect.Method;
public class ReflectMain {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String className = args[0];
Method mainMethod = Class.forName(className).getMethod("main",
String[].class);
mainMethod.invoke(null, (Object) new String[] { "abc", "def", "hgi" });
// 注意此处代码,可以写成(Object)new String[]{"abc","def","hgi"}也可以写成new
// Object[]{new String{“abc”,”def”,”hgi”}}但不可以写成new
// String[]{“abc”,”def”,”hgi”}
}
}
class TestMain {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
数组的反射:
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用,非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用
判断一个Object对象是不是数组?
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------