zoukankan      html  css  js  c++  java
  • JavaSE基础入门_018_反射

    反射

    什么是类对象

    • 类的对象:基于某个类 new 出来的对象,也称为实例对象。

    • 类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)

     

    获取类对象

    • 1、通过类的对象,获取类对象

      • Student s = new Student();
        Class c = s.getClass();
    • 2、通过类名获取类对象

      • Class c = 类名.class;
    • 3、通过静态方法获取类对象【推荐使用】

      • Class c = Class.forName("包名.类名");

     

    常用方法

    • public String getName();//获取类对象所代表的类名

      public Package getPackage();//当前类对象所在的包

      public Class<? super T> getSuperclass();//获取当前类的父类

      public Class<?>[] getInterfaces();//获取当前类所实现的所有接口

      public Constructor<?>[] getConstructors();//获取当前类的所有公共构造类对象

      public T newInstance();//使用当前类对象来创建一个实例

      public Method[] getMethods();//获取类的方法

      public Field[] getFields();//获取 自身+父类 的公开属性

     

    • // 1,使用反射获取类的名字、包名、父类、接口
      public static void reflectOpe1() throws Exception{
      Class<?> class1 = Class.forName("getClassName.Person");
      System.out.println(class1.getName());
      System.out.println(class1.getPackageName());
      System.out.println(class1.getSuperclass().toString());
      System.out.println(class1.getInterfaces().toString());
      }

      // 2,使用反射获取类的构造方法,创建对象
      public static void reflectOpe2() throws Exception{

      // 2.1:获取类对象
      Class<?> class2 = Class.forName("getClassName.Person");

      // 2.2:获取类的构造方法
      // Constructor<?>[] cons = class2.getConstructors();
      // for (Constructor<?> con : cons) {
      // System.err.println(con.toString());
      // }

      // 2.3: 获取类中无参构造
      Constructor<?> con = class2.getConstructor();// 不给参数就是获取无参构造
      Person zhangsan = (Person)con.newInstance();// 利用构造方法新建一个实例对象,这里就是一个 Person 类型
      System.out.println(zhangsan.toString());
      //简便无参构造方法,创建实例对象;类对象.newInstance()
      Person wang5 = (Person)class2.newInstance();
      System.out.println(wang5.toString());

      // 2.4: 获取类中的带参构造方法
      Constructor<?> con2 = class2.getConstructor(String.class,int.class);
      Person xiaoli = (Person)con2.newInstance("小李",20);
      System.out.println(xiaoli.toString());
      }

      // 3,使用反射获取类中的方法,并调用方法
      public static void reflectOpe3() throws Exception {
      // 3.1,获得类对象
      Class<?> class1 = Class.forName("getClassName.Person");

      // 3.2,获取类方法
      // 3.2.1, 类对象.getMethods() 只能获取公开的方法,包括从父类继承的方法
      // Method[] methods = class1.getMethods();
      // 3.2.2, 类对象.getDeclaredMethods() 获取类自身中所有方法,包括私有,默认,保护;不包含继承的
      // Method[] methods = class1.getDeclaredMethods();
      // for (Method method : methods) {
      // System.out.println(method);
      // }

      // 3.3, 获取单个方法

      // 3.3.1 获取 eat()
      Method eatmethod = class1.getMethod("eat");
      // 调用方法
      // 正常一般的调用:对象.方法()
      //eatmethod.invoke(obj, args)
      Person zhang3=(Person)class1.newInstance();
      // eatmethod.invoke(zhang3);// 相当于:zhang3.eat()
      // System.out.println("----------------------------");

      // 3.3.2 获取toString()
      // Method toStringMethod = class1.getMethod("toString");
      // System.out.println(toStringMethod.invoke(zhang3));
      // System.out.println("----------------------------");

      // 3.3.3 获取eat(String food), 带参数的方法
      // Method eat2 = class1.getMethod("eat", String.class);
      // eat2.invoke(zhang3, "鸡腿");

      // 3.3.4 获取私有方法
      Method privatemethod = class1.getDeclaredMethod("privateMehod");

      // private方法被反射调用时,需要设置其访问权限无效
      privatemethod.setAccessible(true);//压制访问检查
      privatemethod.invoke(zhang3);

      // 3.3.5获取静态方法
      Method staticMethod = class1.getMethod("staticMethod");
      staticMethod.invoke(null);
      }

      // 4,使用反射实现一个可以调用任何对象方法的通用方法
      // 参数:对象,方法名,方法参数类型数组,参数
      public static Object invokeAny(Object obj,String methodName,Class<?>[] types,Object...args) throws Exception{
      // 4.1.获取类对象
      Class<?> class1 = obj.getClass();

      // 4.2.获取方法
      Method method = class1.getMethod(methodName, types);

      // 4.3.调用
      return method.invoke(obj, args);
      }

      // 5,使用反射获取类中的属性
      public static void reflectOpe4() throws Exception {
      // 5.1.获取类对象
      Class<?> class1 = Class.forName("getClassName.Person");

      // 5.2.获取属性
      // Field[] fields = class1.getFields();//只能拿 public 字段
      // Field[] fields = class1.getDeclaredFields();// 除了继承的,他自己声明的所有都可以获取
      // System.out.println(fields.length);
      // for (Field field : fields) {
      // System.out.println(field);
      // }

      // 5.3.获取name属性

      Field field = class1.getDeclaredField("name");
      // 私有属性,需要设置绕过java检查,修改访问权限
      field.setAccessible(true);
      System.out.println(field);

      // 5.4.给获取到的属性 赋值
      Person zhangsan = (Person) class1.newInstance();

      field.set(zhangsan , "z3");// zhangsan.name = "z3";
      // 5.5. 获取属性值
      Object result = field.get(zhangsan);//zhangsan.name
      System.out.println(result);

      }
    • 注意:反射是一种 Java 的底层技术,可以突破封装。使用起来比较危险。

    • 使用反射:解决通用编程的问题,需要使用反射。

     

    设计模式介绍

    • 什么是设计模式

      • 一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。简单理解:特定问题的固定解决方法。

    • 好处:

      • 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、重用性。

    • 在GOF的《设计模式》书中描述了23种设计模式

     

     

    工厂设计模式

    • 工厂模式主要负责对象创建的问题。

    • 开发中有一个非常重要的原则 “开闭原则”,对拓展开放、对修改关闭。

    • 可通过反射进行工厂模式的设计,完成动态的对象创建。

     

    单例设计模式

    • 单例(Singleton):只允许创建一个该类的对象。

    • 方式1:饿汉式(类加载时创建,天生线程安全)

      • class Singleton{
           // 1. 用 Singleton 类,创建一个静态常量
           private static final Singleton instance = new Singleton();
           // 2. 修饰构造方法为私有
           private Singleton(){}
           // 3. 返回创建的常量
           public static Singleton getInstance(){
               return instance;
          }
        }
    • 方式2:懒汉式(使用时创建,线程不安全,加同步)

      • 迫切创建唯一对象

      • class Singleton{
           // 1. 用 Singleton 类,创建一个静态常量
           private static Singleton instance = null;
           // 2. 修饰构造方法为私有
           private Singleton(){}
           // 3. 返回创建的常量
           public static Synchronized Singleton getInstance(){
               if(instance == null){
                   instance = new Singleton();
              }
               return instance;
          }
        }
    • 方式3:线程安全的懒汉式(使用时创建,线程安全)

      • class Singleton{
           
           private Singleton(){}
           
           private static class Holder{
               static Singleton s = new Singleton();
          }

           public static Synchronized Singleton getInstance(){
               return Holder.s;
          }
        }

     

    枚举

    • 什么是枚举

      • 枚举是一个引用类型,枚举是一个规定了取值范围的数据类型。

    • 枚举变量不能使用其他的数据,只能使用枚举中常量赋值,提高程序安全性。

    • 定义枚举使用: enum 关键字

    • 枚举的本质:

      • 枚举是一个终止类,并继承Enum抽象类。

      • 枚举中常量是当前类型的静态常量。

     

    注解

    • 什么是注解

      • 注解(Annotation)是代码里的特殊标记,程序可以读取注解,一般用于替代配置文件。

     

    • 开发人员可以通过注解告诉类如何运行。

      • 在 Java 技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。

     

    • 常见注解:@Override

     

    • 定义注解使用 @interface 关键字,注解中只能包含属性

     

    • 注解属性类型

      • String 类型

      • 基本数据类型

      • Class 类型

      • 枚举类型

      • 注解类型

      • 以上类型的一维数组

     

    • 注解的本质:接口;它的属性实质是:抽象方法。

     

    • 元注解:用来描述注解的注解。

      • @Retention:用于指定注解可以保留的域

        • RetentionPolicy.CLASS:注解记录在 class 文件中,运行 Java 程序时,JVM不会保留。这是默认值
        • RetentionPolicy.RUNTIME:注解记录在 class 文件中,运行 JAVA 程序时,JVM会保留注解,程序可以通过反射获取该注释
        • RetentionPolicy.SOURCE:编译时直接丢弃这种策略的注释
        • // 代码使用演示:
          @Retention(value = RetentionPolicy.RUNTIME)
          public @interface PersonInfo {
          String name();
          int age();
          String sex();
          }
      • @Target:指定注解用于修饰类的哪个成员。

        • @Target(value = { ElementType.METHOD })//注解的使用范围
          //这个注解:指定此注解只能 打在 方法上面

     

    总结

    • 类对象:

      • Class对象,封装了一个类的所有信息;程序运行中,可通过Class对象获取类的信息。

    • 获取类对象的三种方式:【推荐第三种,依赖方式最低】

      • Class s = 对象.getClass();
        Class s = 类名.class;
        Class s = Class.forName("包名.类名");
    • 工厂模式:

      • 主要用于创建对象,通过反射进行工厂模式的设计,完成动态对象创建。

    • 单例模式:

      • Singleton,只允许创建一个该类的对象。

    • 枚举类型

    • 注解类型

  • 相关阅读:
    每天一个设计模式(2):观察者模式
    每天一个设计模式(1):策略模式
    每天一个设计模式(0):设计模式概述
    常量池、栈、堆的比较
    常量池小结
    Java虚拟机体系结构分析
    Java并发(3):volatile及Java内存模型
    第一题:Big Countries
    22 高级SQL特性
    21 使用游标
  • 原文地址:https://www.cnblogs.com/77-is-here/p/13163756.html
Copyright © 2011-2022 走看看