java反射(易懂)

1、反射的介绍

(1)Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行 期 借助于ReflectionAPI取得任何类的内部信息,并能直接操作任意对象的内 部属性及方法。
(2)加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。

2、反射API

2.1、获取类对应的字节码的对象(三种)

1.调用某个类的对象的getClass()方法,即:对象.getClass();

 User user  = new User();
 Class uClass= user.getClass();
  1. 调用类的class属性类获取该类对应的Class对象,即:类名.class
Class userClass = User.class;
  1. 使用Class类中的forName()静态方法(最安全,性能最好)即:Class.forName(“类的全路径”)
Class aClass = Class.forName("com.ref.User");

2.2、Class类的常用方法

//返回指定类名namegClass对象
1.static glassforName(String name)
//返回指定类名namegClass对象
2.Object newlnstance()
//调用缺省构造函数,返回Class对象的一个实例
3.getName()
//返回此Class对象所表示的实体(类,接口,数组类或void)的名称。
4.Class getSuperClass()
//返回当前Class对象的父类的Class对象获取当前Class对象的接口
5.Class[] getinterfaces()
//返回该类的类加载器
6.ClassLoader getClassLoader()
//返回一个包含某些Constructor对象的数组
7.Constructor[]getConstructors()
//返回一个Method对象,此对象的形参类型为paramType
8.Method getMothed(String name,Class.. T)
//返回Field对象的一个数组
9.Field[] getDeclaredFields()

2.3、哪些类型可以有class对象

1.class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类。
2.interface:接口
3. [ ]:数组
4. enum:枚举
5. annotation:注解 @interface
6. primitive type:基本数据类型
7. void

        Class c1 = Object.class; //类
        Class c2 = Comparator.class; //接口
        Class c3 = String[].class; //数组
        Class c4 = int[][].class; //二维数组
        Class c5 = Override.class; //注解
        Class c6 = ElementType.class; //枚举
        Class c7 = Integer.class; //基本数据类型
        Class c8 = void.class; //void
        Class c9 = Class.class; //Class

运行结果

class java.lang.Object
interface java.util.Comparator
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class

Process finished with exit code 0

3、反射在类的应用

3.1、创建类对象

package com.ref;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private Integer id;
    //普通方法
    public void say(){
        System.out.println("卷起来,伙计们");
    }
    public void play(){
        System.out.println("玩起来,伙计们");
    }
}

3.2、获取class对象

  //通过包名获取class对象
  Class<?> aClass = Class.forName("com.ref.User");
  //通过class类获取class对象
  Class<User> userClass = User.class;
  //通过User类的对象获取class对象
  Class<? extends User> aClass1 = new User().getClass();
  //返回值为true 验证了一个类只有一个class对象
  System.out.println(aClass.hashCode()==userClass.hashCode());
  //打印的是User类对应的字节码对象
  System.out.println(aClass);//class com.ref.User
  //获取User类对应的字节码对象userClass的名字
  System.out.println(userClass.getName());//com.ref.User
  //通过User类对应的字节码对象,获取User类的类名
  System.out.println(aClass.getSimpleName());//User
  //通过User类对应的字节码对象,获取User类对应的包对象
  System.out.println(aClass.getPackage());//package com.ref
  //通过User类对应的字节码对象,先获取User类对应的包对象,再获取这个包对象的名字
  System.out.println(aClass.getPackage().getName());//com.ref

3.3、获取类的属性并设置属性值

    Class c1 = User.class;
        Field[] fields = c1.getFields();//获取public的属性值
        for(Field field:fields){
            //属性都是private修饰 输出为null
            System.out.println(field);
        }
        fields = c1.getDeclaredFields();
        for(Field field:fields){
            //输出: private java.lang.String com.ref.User.name
            //     private java.lang.Integer com.ref.User.id
            System.out.println(field);
        }
       Field name = c1.getDeclaredField("name");
//不能直接操作因为是**私有属性**,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true) .
        name.setAccessible(true);
        name.set(user,"神仙");
        //输出:神仙
        System.out.println(user.getName());     

3.4、调用普通方法

 Class c1 = User.class;
 //通过反射调用普通方法
 User user =(User)c1.newInstance();
 //通过反射获取一个方法
 Method setName = c1.getDeclaredMethod("setName", String.class);
 //invoke :激活的意思
 //(对象名,"方法的值")
 setName.invoke(user,"大学生");
  //输出:大学生
 System.out.println(user.getName());

4、创建对象的5种方式

new关键字

 User user = new User();

Class.newInstance方法

//通过反射获取类对象
Class<User> userClass = User.class;
//通过类对象创建
 User user = userClass.newInstance();

Constructor.newInstance方法

 Class<User> userClass = User.class;
 //通过构造器创建对象
 Constructor<User> declaredConstructor =  userClass.getDeclaredConstructor();
User user = declaredConstructor.newInstance("张三", 20);

Clone方法

无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。 要使用clone方法,我们必须先实现Cloneable接口并复写Object的clone方法。

public class User implements Cloneable {
    private String name;
    private Integer id;
    @Override
    public User clone() throws CloneNotSupportedException {
        return (User) super.clone();
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        User user = new User();
        Object clone = user.clone();
        //false
        System.out.println(clone == user);
    }
}

反序列化

1、通过序列化,将对象的状态写在流里面:
先构造一个对象流ObjectOutputStream oss,使用oos的writeObject的方法将实例对象user1的状态写到流(字节流文件user1.ser)里面。
2、根据需要把该流读取出来重新构造一个相同的对象:
先构造一个对象流ObjectInputStream ois读取字节流文件user1.ser,使用ois的readObject的方法重新构造一个相同的对象user1。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private String name;
    private Integer id;
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user1.ser"));
        User user1 = new User("张三",10);
        oos.writeObject(user1);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user1.ser"));
        User user2 = (User) ois.readObject();
        System.out.println("user2"+user2);
        ois.close();
    }
}

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值