• 中文
    • English
  • 注册
  • 查看作者
  • Java 反射

    Java 反射表示重要反射机制问题这种方法贼牛X,也就是通过外部文件配置,在不修改源码的情况下,来控制程序,也符合设计模式的 ocp原则(开闭原则:不修改源码,扩容功能)

    可以通过修改properties 配置文件的method的配置,实现修改程序的表现方式。

    举例子:

    src\re.properties 文件

    classfullpath = opp3.Catmethod=cry // 如果 cry 改为 hi 则会改变Cat.class

    package opp3;

    public class Cat {private String name = “招财”;public void hi(){System.out.println(“hi,招财”);}public void cry(){System.out.println(“hi,喵喵叫”);}}ReflectionQuestion.class

    package opp3;

    import javax.swing.plaf.synth.SynthOptionPaneUI;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Properties;

    /**

    • 反射问题的引入*/public class ReflectionQuestion {

    • public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {//根据配置文件 re.properties 指定信息,创建Cat对象并调用hi方法

    // Cat cat = new Cat();// cat.hi();

    }反射原理图java.reflection

    Java 反射插图

    反射相关的主要类java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量java.lang.reflect.Constructor:代表类的构造方法,Constructor表示构造器这些类在java.lang 包

    package opp3;

    public class Cat {private String name = “招财”;public int age = 10;public Cat(){} //无参构造器public Cat(String name){ this.name = name; }public void hi(){System.out.println(“hi,招财”);}public void cry(){System.out.println(“hi,喵喵叫”);}

    }classfullpath = opp3.Catmethod=crypackage opp3;

    import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Properties;

    public class demo01 {public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

    // Field field = cls.getField(“name”); //getField 不能得到private私有的属性 private String name = “招财”;Field field = cls.getField(“age”);// 传统写法: 对象.成员变量 , 反射:成员变量对象.get(对象)System.out.println(field.get(cat)); // public int age = 10;

    }反射调用优化反射的

    ​ 优点:可以动态的创建和使用对象(也可以是框架底层核心),使用灵活,没有反射机制,框架即时就是去底层支撑

    ​ 缺点:使用反射基本就是解释执行,对执行速度有影响

    package opp3;

    import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;

    public class demo02 {public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {m1();m2();

    }稍微优化一下 setAccessible(true);

    setAccessible:启动和禁用访问安全检查的开关。参数值为true则指反射的对象在使用时应该取消java语言访问检查。

    提高反射效率。如果代码中必须使用反射,而该句代码需要频发的被调用,那么请设置为true使得原本无法访问的私有成员也可以访问package opp3;

    import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;

    public class demo02 {public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {m1();m2();m3();

    }Method的setAccessible优化

    Method hi = cls.getMethod(“hi”);hi.setAccessible(true);Field的setAccessible优化

    Field name = cls.getField(“name”);name.setAccessible(true);

    //因为原来的的属性是private,不能直接访问,所以需要关闭安全检测 private String name = “招财”;Class类Class也是类,因此也继承Object类Class类对象不是new 出来的,而是系统生成的对于某个类的Class类对象,在内存中只有一份,因此类只加载一次每个类的实例都会记得自己是哪个Class实例所生成通过Class可以完整地得到一个类的完整结构,通过一些列APIClass对象是存放在堆中类的字节码二进制数据,是放在方法区,有的地方称为类的元数据(包括 方法代码,变量名,方法名,访问权限等等)Java 注解与反射 基础插图

    获取Class对象的六种方法package opp3;

    /**

    • 演示getClass()*/public class GetClass {public static void main(String[] args) throws ClassNotFoundException {

    • }}哪些类型有Class对象class:外部类、成员(内部成员、外部成员),局部内部类,匿名内部类

    interface:接口

    [] :数组

    enum:枚举

    annotation:注解@interface

    primitive type:基本数据类型

    void

    package opp3;

    import java.io.Serializable;

    public class TypeClass {public static void main(String[] args) {Class stringClass = String.class; //外部类Class serializableClass = Serializable.class; //接口Class aClass = Integer[].class; //数组Class aClass1 = float[][].class; //二维数组Class deprecatedClass = Deprecated.class; //注解//枚举Class stateClass = Thread.State.class;Class longClass = long.class; //基本数据类型Class voidClass = void.class; //void数据类型Class classClass = Class.class;

    }}类加载静态和动态加载静态加载:编译时加载相关类,如果没有则报错,依赖性太强动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低依赖性类加载时机:

    当创建对象时(new) //静态加载当子类被加载时,父类也加载 //静态加载调用类种的静态成员时 //静态加载通过反射package opp3;

    import java.lang.reflect.Method;

    public class ClassLoad_ {public static void main(String[] args) throws Exception {// //静态加载,依赖性很强// //编译前必须有Cat类,否则会报错// Cat cat = new Cat();// cat.hi();

    }类加载流程图Java 反射插图2

    Java 反射插图3

    类加载的五个阶段一、加载

    二、验证阶段:

    目的是为了去额宝Class文件的字节流种包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全包括:文件格式验证(是否以魔数 oxcafebabe开头)、元数据验证、字节码验证和符号引用验证可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机加载时间(只要你项目足够大,小项目就不考虑)三、准备阶段:

    //1. n1 是实例属性,不是静态变量,因此在准备阶段不会分配内存//2. n2 是静态变量,分配内存n2 是默认初始化 0 ,而不是20//3. n3 是static final 常量,它和静态变量不一样,因为一旦赋值就不边 n3 = 30

    // class内部//属性-成员变量-字段

    public int n1 = 10;public static int n2 = 20;public static final int n3 = 30四、解析 阶段

    ​ 虚拟机将常量池内的符号引用替换为直接引用的过程

    五、初始化

    到初始化阶段,才正在执行类中定义的java程序代码,此阶段是执行()方法的过程()方法是按语句在源文件中出现的顺序,依次自动收集类中所有的静态变量的赋值动作和静态代码块中的语句,并进行合并虚拟机会保证一个类()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的()方法,其他线程都需要阻塞等待,知道活动线程执行()方法完毕。反射获取类的结构信息第一组:

    getName(); 获取全类名getSimpleName(); 获取简单类名getFields(); 获取所有public修饰的属性,包括父类的getDeclaredFields(); 获取本类中所有属性getMethods(); 获取多有的public修饰的方法,包括父类的getDeclaredMethods(); 获取本类所有的方法getConstructors(); 获取本类所有public修饰的构造器getDeclaredConstructors(); 获取本类中所有的构造器getPackage(); 以package形式返回父类信息getSuperclass(); 以class形式返回父类信息getInterfaces(); 以Class[]形式返回接口信息getAnnotations(); 以Annotations[]形式返回注解信息package opp3;

    import org.testng.annotations.Test;

    import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;

    /**

    • 如何获取类的结构信息*/

    public class Demo05 {public static void main(String[] args) throws Exception{api_01();}

    }

    class A {public String hobby;public A(){}}

    interface IA{

    }interface IB{

    }@Deprecatedclass Person extends A implements IA,IB{public String name;protected int age;String job;private double sal;

    }第二组:java.lang.reflect.Field类

    getModifiers :以int 形式返回修饰符

    ​ (说明:默认修饰符是0 , public 是1 , private是2, protected是 4 ,static是8, final 是16)

    ​ 其他的举例说明:修饰符 public static:1+8 = 9

    getType:以Class形式返回类型

    getName : 返回属性名

    public void api_02() throws Exception{Class cls = Class.forName(“opp3.Person”);Field[] declaredFields = cls.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(“本类的所有属性 ” + declaredField.getName()+” 该属性的修饰符值 ” + declaredField.getModifiers()+ ” 该属性的类型 ” + declaredField.getType());}}第三组:java.lang.reflect.Method类

    getModifiers :以int 形式返回修饰符

    (说明:默认修饰符是0 , public 是1 , private是2, protected是 4 ,static是8, final 是16)

    getReturnType: 以Class形式获取 返回类型

    getName:返回方法名

    getParameterTypes:以Class[]返回参数类型数组

    package opp3;

    import org.testng.annotations.Test;

    import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Type;

    /**

    • 如何获取类的结构信息*/

    public class Demo05 {public static void main(String[] args) throws Exception{api_01();}

    }

    class A {public String hobby;public A(){}}

    interface IA{

    }interface IB{

    }@Deprecatedclass Person extends A implements IA,IB{public String name;protected int age;protected static int id; //修饰符值 : 4 + 8 = 12String job;private double sal;

    }第四组:java.lang.reflect.Constructor类

    getModifiers :以int 形式返回修饰符

    (说明:默认修饰符是0 , public 是1 , private是2, protected是 4 ,static是8, final 是16)

    getName:返回构造器名(全类名)

    getParameterTypes:以Class[]返回参数类型数组

    package opp3;

    import org.testng.annotations.Test;

    import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Type;

    /**

    • 如何获取类的结构信息*/

    public class Demo05 {public static void main(String[] args) throws Exception{api_01();}

    }

    class A {public String hobby;public A(){}}

    interface IA{

    }interface IB{

    }@Deprecatedclass Person extends A implements IA,IB{public String name;protected int age;protected static int id; //修饰符值 : 4 + 8 = 12String job;private double sal;

    }反射爆破创建实例方式一:调用类中的public修饰的无参构造器方式二:调用类中的指定构造器Class类相关方法newInstance:调用类中的无参构造器,获取对应类的对象getConstructor(Class…clazz):根据参数列表,获取对应的构造器对象getDecalaredConstructor(Class…clazz):根据参数列表,获取对应的构造器对象Constructor类相关说法setAccessible:爆破newInstance(Object…obj):调用构造器package opp3;

    import java.lang.reflect.Constructor;

    /**

    • 通过反射机制创建实例*/public class Demo06 {public static void main(String[] args) throws Exception {

    • }}

    class User{private int age = 500;private String name = “Nahida”;

    }操作属性如何通过反射访问类中的成员

    根据属性名获取Field对象

    ​ Field f = clazz 对象.getDeclaredField(属性名)

    爆破:f.setAccessible(true) //f是Field

    访问

    f.set(o,值); //o表示对象

    syso(f.get(o)); // o表示对象

    如果是静态属性,则set和get中的参数o,可以写成null

    package opp3;

    import java.lang.reflect.Field;

    /**

    • 反射操作属性*/public class Demo07 {public static void main(String[] args) throws Exception {//1.得到Student对应的Class对象Class aClass = Class.forName(“opp3.Student”);

    // name.set(o,”巴巴托斯”); 也可以如下一句:name.set(null,”巴巴托斯”); //因为name是静态static的,所以 o 也可以是null, 【注意】不是静态的的这么写会报错System.out.println(o);System.out.println(name.get(o)); //获取属性值

    }

    class Student{public int age; //公共 agepublic static String name;

    }操作方法如何通过反射访问类中的成员

    访问方法:

    根据方法名获取Method方法对象

    ​ Method f = clazz 对象.getDeclaredMethod(方法名, XX.class) //得到本类所有方法

    获取对象:Object o = clazz.newInstance();

    爆破:m.setAccessible(true); //m是Method

    访问

    Object returnValue = m.invoke(o,实参列表);

    如果是静态属性,则invoke中的参数o,可以写成null

    package opp3;

    import java.lang.reflect.Method;

    /**

    • 演示反射调用发发*/public class Demo08 {public static void main(String[] args) throws Exception {

    // Method hi = aClass.getMethod(“hi”, String.class); //getMethod() 获取公共方法,这里可行,但是私有方法不行不能用//得到hi方法Method hi1 = aClass.getDeclaredMethod(“hi”, String.class); //getDeclaredMethod() 获得类的所有方法,这里也可行hi1.invoke(o,”香菱”);

    }

    class Boss{public int age;private static String name;

    }作业Java 反射插图4

    package opp3.opp32;

    import java.lang.reflect.Field;import java.lang.reflect.Method;

    public class HomeWork {public static void main(String[] args) throws Exception {//1. 得到PrivateTest类对应的Class对象Class cls = Class.forName(“opp3.opp32.PrivateTest”);

    }

    class PrivateTest{private String name = “HelloKitty”;public String getName(){return name;}}Java 反射插图5

    package opp3.opp32;

    import java.lang.reflect.Constructor;import java.lang.reflect.Method;

    public class HomeWork02 {public static void main(String[] args) throws Exception {//1. 利用Class类的forName 得到File类的class对象Class cls = Class.forName(“java.io.File”);//2. 获得所有的构造器Constructor[] declaredConstructors = cls.getDeclaredConstructors();//遍历输出所有的的构造器for (Constructor declaredConstructor : declaredConstructors) {System.out.println(“File的构造器:” + declaredConstructor);}//3. 单独的得到public java.io.File(java.lang.String)Constructor declaredConstructor = cls.getDeclaredConstructor(String.class);String filePath = “e://mynew.txt”;Object file = declaredConstructor.newInstance(filePath); //创建文件File对象//4. 调用createNewFile()方法,创建文件Method createNewFile = cls.getDeclaredMethod(“createNewFile”);createNewFile.invoke(file);//file 的运行类型就是FileSystem.out.println(file.getClass());System.out.println(“文件创建成功”);

    }

  • 0
  • 0
  • 0
  • 19
  • 请登录之后再进行评论

    登录
  • 任务
  • 实时动态
  • 发布
  • 单栏布局 侧栏位置: