反射机制有什么用?java
反射机制的相关类在java.lang.reflect.*;
包下。数组
反射机制相关的重要的类有哪些?安全
java.lang.Class
:表明整个字节码,表明一个类型,表明整个类。工具
java.lang.reflect.Method
:表明字节码中的方法字节码。表明类中的方法。测试
java.lang.reflect.Constructor
:表明字节码中的构造方法字节码。表明类中的构造方法this
java.lang.reflect.Field
:表明字节码中的属性字节码。表明类中的成员变量(静态变量+实例变量)。spa
java.lang.Class
:翻译
public class User{ // Field int no; // Constructor public User(){ } public User(int no){ this.no = no; } // Method public void setNo(int no){ this.no = no; } public int getNo(){ return no; } }
```
java.lang.Class
实例的三种方式。
Class c = Class.forName("完整类名带包名")
。Class c = 对象.getClass();
Class c = 任何类型.class;
public class ReflectTest01 { public static void main(String[] args) { /* Class.forName() 1.静态方法 2.方法的参数是一个字符串 3.字符串须要的是一个完整的类名 4.完整类名必须带有包名。java.lang包也不能省。 */ Class c1 = null; Class c2 = null; try { c1 = Class.forName("java.lang.String");//c1表明String.class文件,或者说C1表明String类型 c2 = Class.forName("java.util.Date");//c2表明Date类型 Class c3 = Class.forName("java.lang.Integer");//c3表明Integer类型 Class c4 = Class.forName("java.lang.System");//c4表明System类型 } catch (ClassNotFoundException e) { e.printStackTrace(); } // Java中任何一个对象都有一个方法:getClass() String s = "abc"; Class x = s.getClass();//x表明String.class字节码文件,x表明String类型 System.out.println(c1 == x);//true (==判断的是对象的内存地址) Date time = new Date(); Class y = time.getClass(); System.out.println(c2 == y);//true(c2和y两个变量中保存的内存地址都是同样的,都指向方法区中的字节码文件) // 第三种方式,Java语言中任何一种类型,包括基本数据类型,它都有.class属性。 Class z = String.class;//z表明String类型 Class k = Date.class;//k表明Date类型 Class f = int.class;//f表明int类型 Class e = double.class;//e表明double类型 System.out.println(x == z);//true } }
Class
的newInstance()
方法来实例化对象newInstance()
方法内部实际上调用了无参数构造方法,必须保证无参构造存在才能够。public class ReflectTest02 { public static void main(String[] args) { // 这是不使用反射机制建立对象 User user = new User(); System.out.println(user); // 下面这段代码是以反射机制的方式建立对象。 try { // 经过反射机制,获取Class,经过Class来实例化对象。 Class c = Class.forName("com.yang.javaSE进阶.反射.bean.User");//c表明User类型 // newInstance()这个方法会调用User这个类的无参数构造方法,完成对象的建立 // 重点是:newInstance()调用的是无参构造,必须保证无参构造器是存在的 Object obj = c.newInstance(); System.out.println(obj); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } }
public class User { public User() { System.out.println("无参构造方法!"); } }
Class.forName("完整类名");
这个方法的执行会致使类加载,类加载时,静态代码块执行。public class ReflectTest03 { public static void main(String[] args) { try { // Class.forName()这个方法的执行会致使类加载 Class.forName("com.yang.javaSE进阶.反射.bean.MyClass"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
public class MyClass{ // 静态代码块在类加载时执行,而且只执行一次。 static{ System.out.println("MyClass类的静态代码块执行了!"); } }
ClassLoader
rt.jar
ext/*.jar
classpath
String s = "abc";
String.class
文件,找到就加载,那么是怎么进行加载的呢?
C:\Program Files\Java\jdk1.8.0_101\jre\lib\rt.jar
。rt.jar
中都是JDK最核心的类库。C:\Program Files\Java\jdk1.8.0_101\jre\lib\ext\*.jar
classpath
中的类。public class ReflectTest04 { public static void main(String[] args) throws Exception { // 获取整个类 Class studentClass = Class.forName("com.yang.javaSE进阶.反射.bean.Student"); // 获取类中全部的Field Field[] fields = studentClass.getFields(); System.out.println(fields.length);//测试数组中只有一个元素 // 取出这个Field Field f = fields[0]; // 取出这个Field的名字 String fieldName = f.getName(); System.out.println(fieldName); // 获取全部的Field Field[] fs = studentClass.getDeclaredFields(); System.out.println(fs.length); // 遍历 for (Field field : fs) { // 获取属性的修饰符 int i = field.getModifiers();//返回的修饰符是一个数字,每一个数字是修饰符的代号! System.out.println(i); // 能够将这个“代号”数字转换成“字符串” String modifierString = Modifier.toString(i); System.out.println(modifierString); // 获取属性的类型 Class fieldType = field.getType(); // String fName = fieldType.getName(); String fName = fieldType.getSimpleName(); System.out.println(fName); // 获取属性的名字 System.out.println(field.getName()); } } }
public class Student { // Field翻译为字段,其实就是属性/成员 // 4个Field,分别使用了不一样的访问控制权限修饰符 public int no; private String name; protected int age; boolean sex; public static final double MATH_PI = 3.1415926; }