Java反射

发布于:2024-06-26 ⋅ 阅读:(175) ⋅ 点赞:(0)

目录

1.回顾

二.反射的概述

2.1Java反射的概念

2.2Java反射的作用

三.Class类

3.1概述

3.2获取类的三种方式

3.2.1 

3.2.2

3.2.3

四.Constructor类

4.1Constuctor方法

4.2具体实例

五.Field类

 六.Method类

 七.反射案例

八.反射的优缺点总结


1.回顾

在了解Java反射之前,我们需要回顾一下之前在java中如何使用类和对象。

1.定义类

public class 类名{
      String name;
      .....
      属性
      public void 方法名(){

      } 
}

2.创建已知类的对象,明确知道要创建哪一个类的对象

这一切都是已知的,这对于我们自己写的程序是没有问题的。

但是像框架,tomcat,或者其他的组件(jackson 对象 -->json),事先是不知道具体要处理哪些类的,

只能根据配置文件中配置的类的地址决定要创建并操作哪个类。

那么问题来了,如果我们只知道类的地址,如何使用类?

<servlet-class>com.ffyc.dormserver.web.LoginServlet</servlet-class>
<servlet-class>com.ffyc.dormserver.web.BuildServlet</servlet-class>

框架可以做到给他什么类名,就可以创建给定类的对象,并调用该对象的方法和属性。

1.创建对象

2.将查询到的结果封装到我们创建的对象中(调用setxxx() 调用xxx属性)

那如何实现写一条程序可以处理任何类呢?

答案就是反射机制。

反射机制,可以看做是一种反向使用类。

二.反射的概述

2.1Java反射的概念

Java反射机制是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能被称为Java语言的反射机制。

2.2Java反射的作用

动态获取类的信息

三.Class类

3.1概述

一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象。

Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本 信息。

  • 一个类在堆中只有一个Class对象,这个Class对象包含了类的完整结构信息
  • 在使用反射的过程中,把方法、属性、构造器都当做对象来处理的
  • Class类对象由系统创建,继承了Object类

3.2获取类的三种方式

3.2.1 

Object类中的getClass方法:适用于1通过对象获得Class实例的情况

 User user = new User();
 Class class = user.getClass();//通过已知的对象中getClass()方法 获得该对象的Class对象

3.2.2

类名.class方式:适用于通过类名获得Class实例的情况

 User user = new User();
  Class class = User.class;

3.2.3

Class类的静态方法 forName(String name)

String s = "com.ffyc.javareflect.Demo2.User";
Class class =  Class.forName(s);//把给定地址的类进行加载,为其创建class对象
四.Constructor类
4.1Constuctor方法

public String getName()

返回构造方法名

public T newInstance(Object … initargs)

创建对象【参数为创建对象的数据】

4.2具体实例

getConstructor( )   

获得类中指定的公共构造方法 将获得到的无参构造方法封装到一个 Constructor对象中

getDeclaredConstructor( )

获得类中指定的构造方法(包含私有的)

getConstructors( )

获得所有公共的构造方法

getDeclaredConstructors( )

获得所有的构造方法(包含私有的)

getName( ):返回构造器的全类名
setAccessible( ):爆破,访问私有成员
newInstance( ):创建对象

package com.ffyc.javareflect.Demo2;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Text3 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        String s = "com.ffyc.javareflect.Demo2.User";

        //加载类,并获得Class对象
        Class c = Class.forName(s);
        //通过Class类的对象,来创建User对象
        //Object userobject = c.newInstance();
        //System.out.println(userobject);

        //获取类中的构造方法信息
        Constructor constructor =  c.getConstructor();//获得类中指定的公共构造方法 将获得到的无参构造方法封装到一个 Constructor对象中
        Object userobject = constructor.newInstance();//通过构造方法中的newInstance()创建对象
        System.out.println(userobject);

        Constructor constructor1 = c.getDeclaredConstructor();//获得类中指定的构造方法(包含私有的)

        Constructor constructor2 = c.getConstructor(String.class,String.class);//获得公共的有参构造方法
        Object userobject1 =  constructor2.newInstance("111","222");//创建对象,并为对象数组赋值
        System.out.println(userobject1);

        Constructor[] constructors = c.getConstructors();//获得所有公共的构造方法
        Constructor[] constructors1 = c.getDeclaredConstructors();//获得所有的构造方法(包含私有的)
        System.out.println(constructors.length);
        System.out.println(constructors1.length);
    }
}

 

五.Field类

getField( ) 

获得类中指定公共的属性,把属性封装到一个Field对象中

getDeclaredField( )

获得类中指定的属性(包含私有,受保护,默认,公共),把属性封装到一个Field对象中

getFields( )

获得类中所有的公共属性

getDeclaredFields( )

获得到所有的属性(包含私有的)

getName( ):返回属性名

package com.ffyc.javareflect.Demo2;

import java.lang.reflect.Field;

public class Text4 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        String s = "com.ffyc.javareflect.Demo2.User";

        Class c = Class.forName(s);//获得类的Class对象

        Object userobject = c.newInstance();//创建User类的对象

        //获得类中的成员变量
        //获得类中指定公共的属性,把属性封装到一个Field对象中
        //Field userNameField =  c.getField("userName");
        //获得类中指定的属性(包含私有,受保护,默认,公共),把属性封装到一个Field对象中
        Field userNameField =  c.getDeclaredField("userName");

        //Field[] fields = c.getFields();
        //System.out.println(fields.length);

        //获得到所有的属性(包含私有的)
        Field[] fields =  c.getDeclaredFields();
        System.out.println(fields.length);
        //循环所有的属性,为属性赋值
        for (Field f : fields){
            f.setAccessible(true);//设置私有属性可以操作
            f.set(userobject,"111");
        }
        System.out.println(userobject);


    }
}
 六.Method类

getMethod( )

getDeclaredMethod( )

getMethods( )

获得本类和父类所有公共的成员方法

getDeclaredMethods( )

获得本类中所有成员方法

getName( ):返回方法的名称

package com.ffyc.javareflect.Demo2;


import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Matcher;

public class Text5 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        String s = "com.ffyc.javareflect.Demo2.User";
        Class c=Class.forName(s);//获得类的Class对象
        Object userobject=c.newInstance();//创建user类的对象

        Method eat=c.getMethod("eat");
        // 执行userobject对象中的 无参的eat方法
        eat.invoke(userobject);

        Method eat1=c.getMethod("eat",String.class);
        eat1.invoke(userobject,"烤肉");

        Method[] methods=c.getMethods();// 获得本类和父类所有公共的成员方法
        Method[] methods1=c.getDeclaredMethods();// 获得本类中所有成员方法
        System.out.println(methods.length);//15
        System.out.println(methods1.length);//7
    }
}
 七.反射案例

我们可以自定义java对象转json工具类

下面是代码实例:

package com.ffyc.javareflect.util;

import com.ffyc.javareflect.Demo1.Car;
import com.ffyc.javareflect.Demo2.User;

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

public class JasonUtil {
    /*
    自定义的对象转json方法 {name:"jim",age:10}
    */
    public String objectToJson(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String json = "{";
        Class c = object.getClass();

        Field[] fields = c.getDeclaredFields();
        for(Field f :fields){
            //生成属性的get方法名
            String get = "get"+(char)(f.getName().charAt(0)-32)+f.getName().substring(1);
            Method getMethod = c.getMethod(get);//通过get方法名 获得方法

            json+=f.getName()+":"+getMethod.invoke(object)+",";
        }
        json = json.substring(0,json.length()-1);
        json+="}";
        return json;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        User user = new User();
        user.setUserName("admin");
        user.setPassword("111");
        Car car = new Car();
        car.setName("大众");
        car.setColor("黑色");

        System.out.println(new JasonUtil().objectToJson(user));
        System.out.println(new JasonUtil().objectToJson(car));
    }
}
八.反射的优缺点总结
优点:
● 1. 增加程序的灵活性,可以在运行的过程中动态对类进行修改和操作
● 2. 提高代码的复用率,比如动态代理
● 3. 可以在运行时轻松获取任意一个类的方法、属性,并且还能通过反射进行动态
调用
缺点:
● 1. 反射会涉及到动态类型的解析,导致性能要比非反射调用更低
● 2. 使用反射技术通常要在一个没有安全限制的程序运行 .
● 3. 反射可以绕过一些限制访问的属性或者方法,可能会导致破坏代码本身的抽象

网站公告

今日签到

点亮在社区的每一天
去签到