------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com"
反射基础概述总结:
反射的基本: Class类
Java程序中的各个Java类属于内同一类食物,描述这类事物的Java类名就是Class
类似于Person类代表人,那么同样的Class类代表着一个个的CLass类
Person类可以是一个实例,名叫张三,Class类也可以有一个对象,名叫String.class
如何得到各个类字节码对应的实例对象(Class类型)
类名.class 如:String.class
对象.getClass() 如:new Date().getClass()
Class.forName("类名") 如:Class.forNmae("java.util.Date")
九个预定义Class实例对象
参看Class.isPrimitive方法的帮助文档
Int.class == Integer.TYPE
数组类型的Class实例对象
Class.isArray()
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[], void ...
2、反射的概念
反射就是把Java类中的各种成份映射成相应的java类。
例如:一个Java类中用一个Class类的对象来表示,
一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示。
表示Java类中的Class类显然要提供一系列的方法,来获得其中的变量(Field),方法(Method),构造方法(Constructor),修饰符, 包(Package)等信息
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。
通过调用Class类方法可以得到这些实例对象
3、Constructor类
代表某个类中的构造方法
得到某一个类的所有构造方法
Constructorcon=Class.forName("java.lang.String").getConstructor();
得到某一个类的某一个构造方法
Constructorcon=Class.forName("java.lang.String").getConstructor(StringBuffer.class);
创建实例对象:
通常方法:String str =new String(newStringBuffer("abc"));
反射方法:
String str = (String)con.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:
例子:String obj=(String)Class.foName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象
用到了缓存机制来保存默认构造方法的实例对象
4、Field类
代表某个类中的成员变量
得到的Field对象是对应到类上的成员变量
5、Method类
代 表某个类中的成员方法
得到类中的某一个方法:
Method chatAt =Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方法:System.out.println(chatAt.invoke(str,1));
如果传递给Method对象的invoke()方法的一个参数为null,说明该Method对象对应的是一个静态方法
jdk1.4和jdk1.5的invoke方法的区别
jdk 1.5:public Object invoke(Object obj,Object ...arge)
jdk 1.4 public Object invoke(Object obj,Object[] agrs)
即:jdk 1.4传递的参数是数组形式,jdk 1.5是可变参数形式
6、数组的反射
具有相同维数的数组属于同一个类型,即具有相同的Class实例对象
代表数组的Class实例对象的getSuperClass()方法返回的父类位Object类对应的Class
基本类型的以为数组可以被当作Object类型使用,不能当作Object[]类型使用
非基本类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用
Array.asList()方法处理int[]和String[]是的差异,
Array工具类用于完成对数组的反射的操作。
7、反射的作用——实现框架功能
框架与框架要解决的核心问题
我们在写的框架,相当一间毛坯房,写好了之后又用户住进来会进行装修,变成自己的个性的房子。相当于其他程序员调用我们这 个框架,在这个基础上来写他的程序。
因为在写程序是无法知道要被调用的类名,所以,在程序中无法new某个类的实例对象,所以要用反射方式来做。
--------------------------------------------------------------------------------------
// 如何生成获取到字节码文件对象的实例对象。
Classclazz = Class.forName("classTest.User");// 类加载
// 直接获得指定的类型
clazz= User.class;
// 根据对象获得类型
Objectobj = new User("ly", 123456);
clazz= obj.getClass();
Objectobj = clazz.newInstance();//该实例化对象的方法调用就是指定类中的空参数构造函数,给创建对象进行初始化。当指定类中没有空参数构造函数时,该如何创建该类对象呢?请看method_2();
public staticvoid method_2() throws Exception {
Classclazz = Class.forName("classTest.User");
//既然类中没有空参数的构造函数,那么只有获取指定参数的构造函数,用该函数来进行实例化。
//获取一个带参数的构造器。
Constructorconstructor = clazz.getConstructor(String.class,int.class);
//想要对对象进行初始化,使用构造器的方法newInstance();
Objectobj = constructor.newInstance("ly",123456);
//获取所有构造器。
Constructor[]constructors = clazz.getConstructors();//只包含公共的
constructors= clazz.getDeclaredConstructors();//包含私有的
for(Constructorcon : constructors) {
System.out.println(con);
}
}
------------------------------------------------------
反射指定类中的方法:
//获取类中所有的方法。
public staticvoid method_1() throws Exception {
Classclazz = Class.forName("classTest.User");
Method[]methods = clazz.getMethods();//获取的是该类中的公有方法和父类中的公有方法。
methods= clazz.getDeclaredMethods();//获取本类中的方法,包含私有方法。
for(Methodmethod : methods) {
System.out.println(method);
}
}
//获取指定方法;
public staticvoid method_2() throws Exception {
Classclazz = Class.forName("classTest.User");
//获取指定名称的方法。
Methodmethod = clazz.getMethod("abc", String.class,int.class);
//想要运行指定方法,当然是方法对象最清楚,为了让方法运行,调用方法对象的invoke方法即可,但是方法运行必须要明确所属的对象和具体的实际参数。
Objectobj = clazz.newInstance();
method.invoke(obj,"user",123);//执行一个方法
}
//想要运行私有方法。
public staticvoid method_3() throws Exception {
Classclazz = Class.forName("classTest.User");
//想要获取私有方法。必须用getDeclearMethod();
Methodmethod = clazz.getDeclaredMethod("method", null);
// 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。
method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。
}
//反射静态方法。
public staticvoid method_4() throws Exception {
Classclazz = Class.forName("classTest.User");
Methodmethod = clazz.getMethod("function",null);
method.invoke(null,null);
}
反射的一些具体用法:
首先我们先准备一个实体类
package classTest;
importjava.io.InputStream;
import java.util.List;
public class User {
//==========================字段(属性)=====================
publicString name = "abc";
privateint password = 123;
privatestatic int age =20;
//====================构造方法===================
publicUser(){
System.out.println("User");
}
publicUser(String name){
System.out.println(name);
}
publicUser(String name,int password){
System.out.println(name+"+"+password);
}
privateUser(List list){
System.out.println("list");
}
//==================普通方法========================
publicvoid abc(){
System.out.println("abc");
}
publicvoid abc(String name,int password){
System.out.println(name+":"+password);
}
publicClass[] abc(String name,int[] password){
returnnew Class[]{String.class};
}
privatevoid abc(InputStream in){
System.out.println(in);
}
publicstatic void abc(int num){
System.out.println(num);
}
publicstatic void main(String[] args) {
System.out.println("main!");
}
publicstatic void abc(int[] args){
System.out.println("aaaa");
}
}
这个实体类中基本包含了对象的各种成分,之后我们就对这个实体类举例
1)、需要获得java类的各个组成部分,首先需要获得类的Class对象,获得Class对象的三种方式:
package classTest;
public class Test1 {
public static void main(String[] args) throws Exception {
//第一种:没有类也没有对象
Class class1 = Class.forName("classTest.User");
//第二种:已知对象
Class class2 = new User().getClass();
//第三种:已知类
Class class3 = User.class;
System.out.println(class1.hashCode());
System.out.println(class2.hashCode());
System.out.println(class3.hashCode());
}
}
运行结果:
User
366712642
366712642
366712642
从结果上我们可以看到三种方式都是调用了无参的构造方法,得到的字节码都是一样的
2)、反射类的成员方法:
importjava.io.FileInputStream;
importjava.io.InputStream;
importjava.lang.reflect.Method;
import org.junit.Test;
public class Test3 {
// 反射类的 方法:public void abc()
@Test
publicvoid test1() throws Exception {
Useruser = new User();
// 加载User类
Classclass1 = Class.forName("classTest.User");
// 解剖User类的方法
Methodmethod = class1.getMethod("abc", null); // 1、那个方法 2、可变参数
method.invoke(user,null);// 1、对象 2、可变参数
}
// 反射类的 方法:public void abc(Stringname,int password)
@Test
publicvoid test2() throws Exception {
Useruser = new User();
// 加载User类
Classclass2 = Class.forName("classTest.User");
// 解剖User类的方法
Methodmethod = class2.getMethod("abc", String.class, int.class); // 1、那个方法 2、可变参数
//通过invoke()调用方法或传参数
method.invoke(user,"fmh", 18);// 1、对象 2、可变参数
}
// 反射类的 方法:public Class[]abc(String name,int[] password)
@Test
publicvoid test3() throws Exception {
Useruser = new User();
// 加载User类
Classclass3 = Class.forName("classTest.User");
// 解剖User类的方法
Methodmethod = class3.getMethod("abc", String.class, int[].class); // 1、那个方法 // 2、可变参数
//通过invoke()调用方法或传参数
Classclass2[] = (Class[]) method.invoke(user, "fmh", new int[] { 1, 2,3});// 1、对象 2、可变参数
System.out.println(class2[0]);
}
// 反射类的 方法:private voidabc(InputStream in)
@Test
publicvoid test4() throws Exception {
Useruser = new User();
// 加载User类
Classclass4 = Class.forName("classTest.User");
// 解剖User类的方法
Methodmethod = class4.getDeclaredMethod("abc", InputStream.class); // 1、那个方法 2、可变参数
method.setAccessible(true);// 暴力放射
//通过invoke()调用方法或传参数
method.invoke(user,new FileInputStream("d:\\fruit.jpg"));// 1、对象 2、可变参数
}
// 反射类的 方法:public static voidabc(int num)
@Test
publicvoid test5() throws Exception {
//User user = new User();
// 加载User类
Classclass5 = Class.forName("classTest.User");
// 解剖User类的方法
Methodmethod = class5.getMethod("abc", int.class); // 1、那个方法 2、可变参数
// 静态方法 可以不用传对象
//通过invoke()调用方法或传参数
method.invoke(null,23);// 1、对象 2、可变参数
}
// 反射类的 方法:public static voidmain(String[] args)
@Test
publicvoid test6() throws Exception {
//User user = new User();
// 加载User类
Classclass6 = Class.forName("classTest.User");
// 解剖User类的方法
Methodmethod = class6.getMethod("main", String[].class); // 1、那个方法 2、可变参数
// 静态方法 可以不用传对象
//通过invoke()调用方法或传参数
method.invoke(null,(Object)newString[]{"aaa","bbb"});// 1、对象 2、可变参数
//反射数组时一定要注意 :::: 数组都拆成这样//main(String s1,Strings2)
//解决方案一:new Object[]{newString[]{"aa","bb"}}
//解决方案二:(Object)newString[]{"aaa","bbb"}
//jdk1.5 method.invoke(Stringmenthodname,object...args)
//jdk1.4 method.invoke(Stringmenthodname,object...obj[])
}
}
以上是反射方法,以及对方法的一些操作