JAVA学习笔记-----反射
来源:互联网 发布:骷髅陷阱升级数据 编辑:程序博客网 时间:2024/05/24 05:58
Class类
世间万物皆对象,包括类也是对象
类也是对象,类是java.lang.Class类的实例对象。任何一个类都是Class类的实例对象,表示方式有三种。
class XXX{}public class Test{ public static void main(String[] args){ XXX x1=new XXX(); }}
Class c1 = XXX.class;
Class c2=xxx.getClass();
Class c3=Class.forName("imooc.reflect.XXX");
引号中为全类名(包括包路径)
这三个Class对象完全等同,c1、c2、c3都代表了X类的“类类型”,一个类只可能是Class类的一个实例对象(故相同)。
通过Class的实例对象,构造具体类的实例对象
要求:该类有无参的构造方法,可通过类类型.newInstance()获取该类的实例。
try{ XXX xxx=c1.newInstance();//需要有无参的构造方法}catch(InstantiationException | IllegalAccessException e){ e.printStackTrace();}
CLass.forName(“类的全称”)
- 不仅表示了类的类类型,还代表了动态加载类
- 区分编译、运行
编译时刻加载类使静态加载类、运行时刻加载类是动态加载类
- new创建对象,是静态加载类,在编译时刻就需要加载所有可能使用到的类。
- 通过动态加载类可以解决静态加载的问题,运行时才加载。
动态加载类代码如下:
try{ Class c=Class.forName(args[0]);//动态加载类,在运行时刻 //通过类类型,创建该类对象 //一般使用父类的引用指向子类的对象 Interface xxx=c.newInstance();}catch(Exception e){ e.printStackTrace();}
基本的数据类型
int、double、String、void等关键字,都存在类类型
Class类的基本API操作
- 首先获取该类的类类型。
class c=obj.getClass();
- 类的名称
c.getName()
返回全类名,如:java.lang.Stringc.getSimpleName()
返回简单类名,如:String - 方法列表
有两种方式获取:
1.Method[] ms=c.getMethods()
获取所有的public方法,包括父类继承而来的
2.Method[] ms=c.getDeclaredMethods()
获取的是所有该类自己声明的方法,不问访问权限(public/protected/defalut/private) - 方法返回值
Class returnType = ms[i].getReturnType();
得到该方法的返回值类型的类类型。 - 方法参数列表
Class[] paramTypes = ms[i].getParameterTypes();
得到的是参数列表的类型的类类型。 - 获取成员变量
Field[] fs=c.getFields();
获取的是所有的public的成员变量的信息,包括继承的Field[] fs = c.getDeclaredFields();
获取的是自己声明的成员变量的信息,不问访问权限
for (Field field : fs) { // 得到成员变量的类型的类类型 Class fieldType = field.getType(); // 获取该成员变量类型的类类型名称 String typeName = fieldType.getName(); // 得到成员变量的名称 String filedName = field.getName(); System.out.println(typeName + " " + filedName); }
- 获取构造函数
构造函数也是对象,java.lang.Constructror中封装了构造函数的信息。获取构造函数同样有两种方法。Constructor[] cs = c.getConstructors()
获取所有的public的构造函数Constructor[] cs = c.getDeclaredConstructors()
得到所有的构造函数,在此处意义不大,因为构造函数都是子类定义的
Constructor[] cs = c.getDeclaredConstructors();for (Constructor constructor : cs) { System.out.print(constructor.getName() + "("); /*获取构造函数的参数列表--->得到的参数列表的类类型*/ Class[] paramTypes = constructor.getParameterTypes(); for (Class class1 : paramTypes) { System.out.print(class1.getName() + ","); } System.out.println(")");}
方法的反射
1)如何获取某个方法
方法的名称和方法的参数列表才能唯一决定某个方法。
2)方法反射的操作 method.invoke(对象,参数列表)
先看代码:
public class MethodDemo1 { public static void main(String[] args) { // 1.获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型 A a = new A(); Class c = a.getClass(); /* * 2.获取方法 名称和参数列表来决定 * getMethod获取的是public的方法 * getDeclaredMethod获取的是自己声明的方法 */ try { // Method m = c.getDeclaredMethod("print", new Class[] {int.class,int.class}); Method m = c.getDeclaredMethod("print", int.class, int.class); // 3. 方法的反射操作 // a.print(10, 20)方法的反射操作,使用m对象来进行方法调用,和a1.print调用的效果相同 // 方法如果没有返回值返回null,有返回值返回具体的返回值 // 效果等同:Object o = m.invoke(a, new Object[] { 10, 20 }); Object o = m.invoke(a, 10, 20); System.out.println("==============================="); Method m1 = c.getMethod("print", String.class, String.class); // 用方法进行反射操作 m1.invoke(a, "hello", "world"); System.out.println("==============================="); // 没有参数就可以不传参数,或者是new Class[]{} // 效果等同:Method m2=c.getMethod("print", new Class[] {}); Method m2 = c.getMethod("print"); // 用方法进行反射操作 // 效果等同:m2.invoke(a, new Class[] {}); m2.invoke(a); } catch (Exception e) { e.printStackTrace(); } }}class A { public void print() { System.out.println("hello world"); } public void print(int a, int b) { System.out.println(a + b); } public void print(String a, String b) { System.out.println(a.toUpperCase() + b.toLowerCase()); }}
步骤1:获取该类的类类型。
A a = new A();Class c = a.getClass();
步骤2:获取该类的某个方法,通过调用c.get(Declared)Method(方法名字符串,参数类类型列表)。
参数类类型列表有两种方式:
①数组的形式传入参数的类类型:Method m = c.getDeclaredMethod("print", new Class[] {int.class,int.class});
②可变参数的形式传入参数的类类型:Method m = c.getDeclaredMethod("print", int.class,int.class);
步骤3:方法的反射操作 Object o = m.invoke(a, 10, 20);
效果等同于:a.print(10,20);
说明:Object o用来接收返回值,若没有返回值则返回null。
通过反射了解集合的泛型
反射的操作都是编译后的操作。泛型是在编译阶段起作用,防止集合中添加错误类型的数据。但是反射的操作可以绕过泛型而向集合中添加非指定的数据。
先看代码:
public static void main(String[] args) { ArrayList list = new ArrayList(); ArrayList<String> list1 = new ArrayList<String>(); list1.add("hello"); Class c1 = list.getClass(); Class c2 = list1.getClass(); System.out.println(c1 == c2); //反射的操作都是编译之后的操作 /* *c1==c2结果返回true,说明编译之后集合的泛型时候去泛型化的, *JAVA中集合的泛型,是防止错误输入的,只在编译阶段有效, *绕过编译就无效了 *验证:我们可以通过方法的反射来操作,绕过编译 * */ try { Method m=c2.getMethod("add", Object.class); m.invoke(list1, 100);// 绕过编译操作就绕过了泛型 System.out.println(list1.size()); System.out.println(list1); /* for (String string : list1) { System.out.println(string); }*/ } catch (Exception e) { e.printStackTrace(); } }
阅读全文
0 0
- Java 反射学习笔记
- Java反射学习笔记
- java反射学习笔记
- Java反射学习笔记
- Java 反射学习笔记
- Java反射学习笔记
- Java学习笔记----反射
- Java反射学习笔记
- Java反射学习笔记
- Java反射学习笔记
- JAVA反射学习笔记
- 反射java学习笔记
- JAVA 反射学习笔记
- Java学习笔记--反射
- Java学习笔记---反射
- JAVA学习笔记-----反射
- 反射学习笔记:Java反射机制
- Java反射机制学习笔记
- 在Java中直接调用js代码
- 加密盐的用途及场景
- axios基本用法
- js全选反选
- opencv(1)qtcreator下环境配置及常见问题
- JAVA学习笔记-----反射
- source insight 保存文件出现File seeking error错误
- navicat for mysql 破解
- EXCEL排序
- canal配置
- 计算机视觉、计算机图形学、图像处理的区别和联系
- js分页
- [SDUT](2119)数据结构实验之链表四:有序链表的归并 ---有序表归并(线性表)
- listview分割线左右边距问题