反射--JavaJEE基础

简介: 反射--JavaJEE基础



一,什么是反射?

1.1 概念:

    反射是指在运行时获取类和对象的相关信息及操作类和对象的方法,反射用于描述该类的属性、方法和构造器等信息。通过反射机制,可以在运行时获取任何一个类的Class对象,并借助Class对象获取该类的相关信息和调用该类的方法。

2.2反射的优缺点:

2.2.1优点:

    在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

2.2.2缺点:

  1. 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射
  2. 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

3.3 反射中的三个类

3.3.1描述:

  Class类、Method类和Field类。Class类是Java反射机制的基础,通过该类可以获取类的名称、修饰符、属性、构造器、方法等信息;Method类和Field类分别用于描述类的方法和属性,可以动态地获取、设置和调用类的方法和属性。

二,类类

2.1 概念

 Class是一个类,代表一个Java类或接口。每个类都有一个对应的Class对象,通过这个对象可以获取类的信息信息,如名称、修饰符、字段(成员变量)、方法、注解、构造函数等,还可以创建类的对象。当一个类被加载到内存中时,会为这个类创建一个对应的Class对象,这个对象包含了当前类的所有信息。通过这个对象,Java程序可以在运行时获取该类的属性、方法、构造函数等信息,并可以通过反射机制实例化对象、调用方法等。

2.2 类类获取三种方式

  1. Class.forName(类的路径)  注意:该方法需要抛出异常Exception,不然会报错
  2. 类实例.getClass
  3. 类名.class

代码如下:

测试的StudentClass类代码:

package com.zking.LiuBing;
public class Student {
  private String sid;
  private String sname;
  public Integer age;
  static{
    System.out.println("加载进jvm中!");
  }
  public Student() {
    super();
    System.out.println("调用无参构造方法创建了一个学生对象");
  }
  public Student(String sid) {
    super();
    this.sid = sid;
    System.out.println("调用带一个参数的构造方法创建了一个学生对象");
  }
  public Student(String sid, String sname) {
    super();
    this.sid = sid;
    this.sname = sname;
    System.out.println("调用带二个参数的构造方法创建了一个学生对象");
  }
  @SuppressWarnings("unused")
  private Student(Integer age) {
    System.out.println("调用Student类私有的构造方法创建一个学生对象");
    this.age = age;
  }
  public String getSid() {
    return sid;
  }
  public void setSid(String sid) {
    this.sid = sid;
  }
  public String getSname() {
    return sname;
  }
  public void setSname(String sname) {
    this.sname = sname;
  }
  public void hello() {
    System.out.println("你好!我是" + this.sname);
  }
  public void hello(String name) {
    System.out.println(name + "你好!我是" + this.sname);
  }
  @SuppressWarnings("unused")
  private Integer add(Integer a, Integer b) {
    return new Integer(a.intValue() + b.intValue());
  }
}

获取StudentClass类类代码:

package com.zking.LiuBing;
/**
 * 类类的获取及反射
 * @author 兵
 *
 */
public class Demo1 {
  public static void main(String[] args) throws Exception {
//    类类获取方式(三种) 要记牢!
//     Class.forName
//     类实例.getClass
//     类名.class
    //实例一个类 
    Student student= new Student();
    //第一种   Class.forName
    //调用了student中无参构造方法    底层实列类的方法就是调的无参构造方法
         Class c1 = Class.forName("com.zking.LiuBing.Student");
    System.out.println("第一种:"+c1);
//    第二种  类实例.getClass
    Class c2 = student.getClass();
    System.out.println("第二种:"+c2);
//    第三种   类名.class
    Class c3= Student.class;
    System.out.println("第三种:"+c3);
  }
}

运行结果:

 

   在反射Student类的时候一定会调用无构造方法,如果在Student中没有无构造方法的话是会运行时会抛出InstantiationException异常,因为通过反射机制创建对象时利用的是无参构造函数实例化对象

三,反射实例化

3.1方法:

  1. newInstance();    创建对象
  2. getConstructor(); 获取对象的构造函数
  3. getDeclaredConstructor(); 获取私有化构造方法
  4. setAccessible(); 修改访问权限的方法 也就是打开访问私有化

注意:参数是反射类的中的方法类型.class

代码展示:

package com.zking.LiuBing;
/**
 * 调用构造方法 
 * 先获取对象的构造函数getConstructor(参数类型.class);  再调用其中的方法newInstance
 * 
 * 
 * 调用构造函数
 * 先获取构造方法getConstructor(类型);  再调用newInstance方法实现
 * 
 */
import java.lang.reflect.Constructor;
public class Demo2 {
  public static void main(String[] args) throws Exception {
    // 获取类类
    Class c1 = Student.class;
    // 实例化反射 在实列反射newInstance创建对象的时候调用的是无参构造方法
    Student s1 = (Student) c1.newInstance();
    System.out.println(s1);
    // Constructor底层parameterTypes它代表了参数的类型
    // 调用一个参数 getConstructor获取对象的构造函数 newInstance创建一个对象
    Constructor cr1 = c1.getConstructor(String.class);
    Student student1 = (Student) cr1.newInstance("s002");
    System.out.println(student1);
    // 调用二个参数
    Constructor cr2 = c1.getConstructor(String.class, String.class);
    Student student2 = (Student) cr2.newInstance("s002", "nb");
    System.out.println(student2);
    // 调用私有化getDeclaredConstructor的方法 不能再用getConstructor它只适用于公共方法中
    Constructor cr3 = c1.getDeclaredConstructor(Integer.class);
    // 如果想调用私有化中的方法需要打开它
    cr3.setAccessible(true);// 打开
    Student student3 = (Student) cr3.newInstance(1);
    System.out.println(student3);
  }
}

运行结果:

 

四,反射动态方法调用

4.1方法:

  1. newInstance(); 创建对象
  2. getMethod(); 获取构造方法名  
  3. getDeclaredMethod();  获取私有化构造函数
  4. invoke(); 调用方法

代码展示:

package com.zking.LiuBing;
/**
 * 调用动态方法    和调用构造方法区别:
 * 调用构造方法:在调用构造的函数的时候没有构造函数名 直接调用参数
 * 调用动态方法:在调用构造的函数的时候前有构造函数名后接参数
 * 
 * 调用动态构造函数
 * 先获取构造方法getMethod(构造函数名,类型);  再调用invoke方法
 * 
 * 私有方法:
 * 先获取构造函数getDeclaredMethod(构造函数名,类型);
 * 打开私有化
 * 再调用方法 invoke3
 * 
 * getMethod是一个可变的方法
 */
import java.lang.reflect.Method;
public class Demo3 {
    public static void main(String[] args) throws Exception {
      //获取类类
    Class c= Student.class;
    //实列反射
    Student stu1 = (Student) c.newInstance();
    //调用无参方法
//    getMethod获取对象  再调用方法
      Method m1= c.getMethod("hello");
      //调用方法
      Object invoke = m1.invoke(stu1);
      System.out.println(invoke);
    //调用有参方法  
//      getMethod是一个可变的方法
     Method m2= c.getMethod("hello",String.class);
     Object invoke2 = m2.invoke(stu1,"大朋友");
     System.out.println(invoke2);
     //调用私有方法  getDeclaredMethod调用私有的对象   
     Method m3=  c.getDeclaredMethod("add", Integer.class,Integer.class);
     m3.setAccessible(true);//打开私有化
     //invoke动态方法
    Object invoke3 = m3.invoke(stu1,2,2);
    System.out.println(invoke3);
    }
}

运行结果:

五,反射读写属性

5.1 方法

  1. getDeclaredFields(); 获取所有对象
  2. getDeclaredField();获取单个属性值

代码展示:

package com.zking.LiuBing;
import java.lang.reflect.Field;
/**
 * 反射读写属性
 * 
 * @author 兵 想要获取值是需要打开私有化的 setAccessible getDeclaredFields获取整条对象 加了s
 *         getDeclaredField获取单个属性 不加s
 */
public class Demo4 {
  public static void main(String[] args) throws Exception {
    // 获取类类
    Class c1 = Student.class;
    // 实列一个对象
    Student student = new Student("002", "小朋友");
    student.age = 3;
    // 打印
    System.out.println("学生id:" + student.getSid() + "学生名称:" + student.getSname() + "年龄:" + student.age);
    // 修改属性值
    Field snamefield = c1.getDeclaredField("sname");
    snamefield.setAccessible(true);// 打开私有化
    snamefield.set(student, "小黑子");// 所需要修改的值
    Field[] field = c1.getDeclaredFields();
    for (Field field2 : field) {// 遍历
      field2.setAccessible(true);// 打开私有化
      // 查看所有
      System.out.println(field2.getName() + "" + field2.get(student));
    }
  }
}

运行结果:

 

目录
相关文章
|
4月前
|
安全 Java
Java反射-Class对象功能概述及反射案例
Java反射-Class对象功能概述及反射案例
40 1
|
11月前
|
安全 Java 程序员
魔法反射--java反射初入门(基础篇)
反射被应用于许多方面, spring的注解, jdbc的连接都是基于反射来实现的, 可能在工作中我们很少能用到反射, 但是在面试的过程中面试官经常会问道, 可以不用反射, 但作为一个程序猿, 还是应该了解了解的
66 0
|
Java 数据处理 数据库
反射到底有什么作用,能帮我们干些什么呢?
反射到底有什么作用,能帮我们干些什么呢?
|
前端开发 编译器 容器
|
开发框架 .NET C#
C#——反射概念和关键类Type
C#——反射概念和关键类Type
104 0
|
缓存 Java Spring
Spring源码学习--new()和反射的实例化区别
本文是博主学习Spring源码的记录,希望对大家有所帮助。
95 0
|
C# 索引
C#反射与特性(八):反射操作的示例大全
C#反射与特性(八):反射操作的示例大全
304 0
|
算法 安全 C#
C#反射与特性(一):反射基础
C#反射与特性(一):反射基础
244 0
C#反射与特性(一):反射基础
C#反射与特性(四 实例化类型
C#反射与特性(四 实例化类型
242 0
C#反射与特性(四 实例化类型