反射
1、反射是Java中的动态机制,它允许我们调用方法或属性,从原来的编码期确定转为在运行期,这大大增加了程序的灵活性,反射会增加程序灵活性,但是会降低性能,所以适度使用
2、Class类
class类的每一个实例表示jvm加载的一个类,所以我们也称其为:类的类对象
jvm加载的每一个类都有且只有一个唯一的Class实例与之对应。我们可以获取摸个类的类对象,
通过它我们可以得知该类的一切信息,例如有类名 属性 方法等甚至可以动态的实例化这个类的
实例,并且调用他的属性和方法。
3、获取一个类的类对象有以下几种方式
1、每个类都有一个静态的属性:class;用于获取该类的类对象,当我们要获取摸个类的对象时
可以采用这个方式,但是由于通过硬编码调用,所以不灵活
例如: 创建一个类 Demo 获取它的信息
Class cls = Demo.class;
2、调用Class的静态方法,动态加载类,该方法要求传入的是加载的类的完全限定名即:包名.类名
Class cls = Class.forName("web.Demo"); // web 包下的 Demo 类完整案例:你可以将以下代码拷贝到你的类中运行,注意里面会有一些小的错误,自己稍作调整就好了
package mvc;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;/*
* invoke执行方法
* field 字段 属性
* declared定义的
*/
public class RefelectDemo {
public static void main(String[] args) {
/*
* 写法一,这种写法不灵活,写死了,我们需要动态加载类
*/
Class cls = Demo.class;
/*
* 写法二,动态加载类
*/
try {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个类名(格式:包名.类名)");
String className = sc.nextLine();
System.out.println("请输入要执行的方法:");
String methodName = sc.nextLine();
Class cl=Class.forName(className);
//获取类名
String clname = cl.getName();
System.out.println("类名:"+clname);
//获取包名
Package clpackage = cl.getPackage();
System.out.println("包名:"+clpackage);
//获取所有方法,包括从父类继承的方法
Method[] methods = cl.getMethods();
for(Method o : methods) {
System.out.println("所有方法,包含从父类继承的方法:"+o.getName());
}
//获取当前类自己定义的方法,不包含继承父类的方法
Method[] methods2 = cl.getDeclaredMethods();
for(Method m : methods2) {
System.out.println("获取自己定义的方法,不包含继承父类的方法"+m.getName());
}
//获取当前类定义的属性
Field[] fields = cl.getDeclaredFields();
for(Field f : fields) {
System.out.println("==="+f.getName());
}
//获取所有的属性,包括继承父类的属性
Field[] fields2 = cl.getFields();
for(Field f : fields2) {
System.out.println(f.getName());
}
//当我们加载好类的时候,就相当于我们创建了一个类,这时候,我们要实例化对象
//当我们创建好了对象之后,我们需要对他进行实例化操作,也就是所谓的new对象
//这里为什么不new呢?因为我们不知道要加载什么类,这个类是我们事先不知道的
//而且实例化的类型是一个Object类型
//类的实例化要求该类必须有无参构造方法,记住,反射的类必须有无参构造方法
Object object = cl.newInstance();
//这里调用的是一个无参方法
Method method = cl.getDeclaredMethod(methodName);
//调用有参方法
//Java 在JDK5 之后推出了一个新特性,可变长参数
//Method method = cl.getDeclaredMethod(methodName, String.class,int.class,....一直加参数.class....);
/*
* 调用该方法
* private void say(){
* syso("hello");
* }
*/
//对于成员方法而言,调用时必须指定该方法所属的对象
method.invoke(object);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}小结: 以上是所有反射的基本认识,需要熟练掌握,反射一般是不常用,他的作用在: 很多框架的底层都是用反射实现的,我们需要掌握原理
3、可变长参数讲解
package reflect;
import java.util.Arrays;
/**
* JDK5之后推出了一个特性:可变长参数
* @author ta
*
*/
public class ArgDemo {
public static void main(String[] args) {
dosome(1,1.1);
dosome(1,1.1,"a");
dosome(1,1.1,"a","b");
dosome(1,1.1,"a","b","c");
dosome(1,1.1,"a","b","c","a","b","c","a","b","c","a","b","c","a","b","c");
}
public static void dosome(int a,double d,String... s) {
System.out.println("length:"+s.length);
System.out.println(Arrays.toString(s));
}
}
4、使用类加载器 ClassLoader 加载类
5、 细说反射
我们之前所有的类都是预先创建一个类,然后呢,给他设置属性方法,这个类是我们需要的,预先知道的类,而且是我们自己定义的
但是,当我们需要使用一些其他的类,而且这个类是我们不知道的类呢?我们不知道它定义的属性和方法,这时候,我们就需要用反射,而且反射提供了动态加载类的方法,这使得我们在用的时候更加灵活方便。而且反射可以强行读取该类的私有属性和方法,不过不建议使用。
package mvc;import java.lang.reflect.Method;
import java.util.Scanner;public class ReflectDemo {
public static void main(String[] args) throws Exception{
/*
* 反射最好的地方就是不知道类 不知道方法名的情况下可以执行,较为常用
* 利用反射调用方法步骤 1、加载类 2、在类中找到方法 3、创建对象 4、在对象上执行方法
* 反射可以强行读取私有属性和方法 ,不建议
*/
Scanner sc = new Scanner(System.in);
System.out.println("输入一个类名");
String className = sc.nextLine();
//Class 是所有反射的入口
//动态加载类
Class<?> cls = Class.forName(className);
//输入方法名
System.out.println("输入方法名");
String methodName=sc.nextLine();
//动态找到类上申明的方法 如果找不到就抛出异常
Method method=cls.getDeclaredMethod(methodName);
//创建动态对象: 现在还不知道类怎么创建对象呢,反射有专门的方法 实例化对象,以前是知道类名才能创建对象,现在是不知道类也可以创建对象
//newInstance的使用前提是类型必须包含无参构造器
Object obj = cls.newInstance();
//在对象上调用方法 如果方法有参数就这样写 method.invoke(obj,方法参数);
//如果参数错误或者对象上没有方法,或者方法执行期间出现故障,都会抛出异常
//Access访问, Accessable 权限可访问的 也就是属性和方法如果是私有的,那么设置了如下代码后会强行访问私有属性和方法
method.setAccessible(true);
Object val = method.invoke(obj);
System.out.println(val);
}
}总结:每个学习Java的人,都需要好好的做笔记,勤于练习,有人说,每天学习基础,很枯燥,很无聊,但是你需要知道,每个无聊的基础,组合成了一个完整的项目。当你的代码足够熟练,自然就能孰能生巧。QQ2951960165
java反射详解
最新推荐文章于 2025-04-19 22:29:36 发布