反射、枚举

本文介绍了Java中的反射机制,包括类的加载过程、反射的原理以及获取Class对象的三种方式,重点阐述了反射的常见方法和动态代理的实现。同时,文章也详细讲解了枚举的定义和使用,指出所有枚举类都是Enum的子类,枚举类的特性及其常用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射

类的加载:
当程序要使用某个类时,如果该类还未被加载到内存中,
则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

    1、加载:
		就是指将class文件读入内存,并为之创建一个Class对象。
		任何类被使用时系统都会建立一个Class对象。
	2、连接:
		验证 :	是否有正确的内部结构,并和其他类协调一致
		准备 :	负责为类的静态成员分配内存,并设置默认初始化值
		解析:	把类中的符号引用转换为直接引用
	3、初始化:
	 	通过构造方法

加载时机:

    1、创建类的实例
	2、访问类的静态变量,或者为静态变量赋值
	3、调用类的静态方法
	4、使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
	5、初始化某个类的子类
	6、直接使用java.exe命令来运行某个主类

类加载器:
负责将.class文件加载到内在中,并为之生成对应的Class对象

分类:
	Bootstrap ClassLoader	根类加载器
	Extension ClassLoader  	扩展类加载器
	Sysetm ClassLoader 		系统类加载器
作用:
	Bootstrap ClassLoader( 根类加载器)
		也被称为引导类加载器,负责Java核心类的加载
		比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
		
	Extension ClassLoader (扩展类加载器)
		负责JRE的扩展目录中jar包的加载。
		在JDK中JRE的lib目录下ext目录
		
	Sysetm ClassLoader (系统类加载器)
		负责在JVM启动时加载来自java命令的class文件,
		以及classpath环境变量所指定的jar包和类路径

反射:
就是在运行状态中的一种动态调用方法或者属性的一种机制

(即获取字节码文件对象,然后剖析该类中存在哪些构造方法,哪些成员变量,哪些成员方法)

获取class文件对象的三种方式:

    1、Object类的getClass()方法
	2、静态属性class
	3、Class类中静态方法forName()
	例:
	一、
	public class test1 {
    public static void main(String[] args) {
       

        Student student = new Student();  s
        //方式1 通过该方法,获取该类对应的字节码文件对象
        Class aClass = student.getClass();
        Class aClass2 = student.getClass();
        System.out.println(aClass == aClass2); //true

        Student student1 = new Student();
        Class aClass3 = student1.getClass();
        System.out.println(aClass2 == aClass3);//true
        System.out.println(student == student1);//false
        
    }
}
class Student {
}
二、
public class test2 {
    public static void main(String[] args) {
        //方式2 通过一个静态属性 class
  
        Class studentClass = Student.class;
        Class studentClass2 = Student.class;
        Class studentClass3 = Student.class;
        System.out.println(studentClass==studentClass2);
        System.out.println(studentClass2 == studentClass3);

    }
}
三、
public class test3 {
    public static void main(String[] args) throws ClassNotFoundException {
       //通过Class类中静态方法forName()
        Class aClass = Class.forName("com.lian.cn.Student");
        Class aClass2 = Class.forName("com.lian.cnStudent");
        System.out.println(aClass==aClass2);
    }
}

反射常见方法

获取构造方法:
1、获取所有构造方法
	public Constructor<?>[] getConstructors() 获取所有的构造方法不包含私有的
	public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法 包括私有的
2、获取单个构造方法
	public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取单个的构造方法 不包含私有的
	public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取单个的构造方
	法包含私有的
	
获取成员变量:
1、获取所有成员变量
	public Field[] getFields() 获取所有的成员变量包含从父类继承过来的
	public Field[] getDeclaredFields() 获取所有的成员变量 包含私有的 也包含从父类继承过来的成员变量
2、获取单个成员变量
	public Field getField(String name)
	public Field getDeclaredField(String name)

获取成员方法:
1、获取所有成员方法
	public Method[] getMethods() //获取所有的公共的成员方法不包含私有的 包含从父类继承过来的过来的公共方法
	public Method[] getDeclaredMethods()//获取自己的所有成员方法 包含私有的
2、获取单个成员方法
	//参数1: 方法名称  参数2:方法行参的class 对象
	public Method getMethod(String name,Class<?>... parameterTypes) //获取单个的方法 不包含私有的
	public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取单个方法包括私有的

属性设置:
public void setProperty(Object obj, String propertyName, Object value){},
	此方法可将obj对象中名为propertyName的属性的值设置为value。

动态代理:

代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
动态代理其实就是通过反射来生成一个代理

动态代理实现:
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,
通过使用这个类和接口就可以生成动态代理对象。

//Proxy类中的方法:

public static Object newProxyInstance(ClassLoader loader,  Class<?>[] interfaces,  InvocationHandler h)
	-loader: 			类加载器
  	-interfaces:		接口对应的一个Class数组
	-InvocationHandler:	这个其实就是要代理对象所做的事情的一个类的封装
		
public Object invoke(Object proxy, Method method, Object[] args)
	- Object proxy: 代理对象
	- Method method:就是UserDaoImpl这个类中的方法对应的实例对象
	- Object[] args:就是每一个方法上需要传递的参数
	
例:
public class MyTest {
    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();     
        UserDao proxy = GetProxyUtils.getProxy(userDao);
        proxy.add();
        System.out.println("----------------");
        proxy.delete();
        System.out.println("----------------");
        proxy.query();
        System.out.println("----------------");
        proxy.update();
  
    }
}
public class GetProxyUtils {
  
    public static UserDao getProxy(UserDao dao) {
        
        UserDao obj = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new InvocationHandler() {
         
           // proxy代理对象、method被代理类中方法的对象、args 方法中的参数
             
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
               //权限校验
                System.out.println("权限的校验");
                Object invoke = method.invoke(dao);
                System.out.println("记录日志");
                return invoke;
            }
        });

        return obj;//返回代理对象
    }
}

public interface UserDao {
    public abstract void add();

    public abstract void delete();

    public abstract void update();

    public abstract void query();
}

public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
       
        System.out.println("增加了一条数据");
      
    }

    @Override
    public void delete() {
   
        System.out.println("删除了一条数据");
    
    }

    @Override
    public void update() {
  
        System.out.println("修改了一条数据");
       
    }

    @Override
    public void query() {
       
        System.out.println("查询一条数据");
       
    }
}
public class UserDaoSon extends UserDaoImpl{
    @Override
    public void add() {
        System.out.println("校验用户权限的代码");
        System.out.println("增加了一条数据");
         System.out.println("记录日志");
    }

    @Override
    public void delete() {
        System.out.println("校验用户权限的代码");
        System.out.println("删除了一条数据");
        System.out.println("记录日志");
    }

    @Override
    public void update() {
        System.out.println("校验用户权限的代码");
        System.out.println("修改了一条数据");
         System.out.println("记录日志");
    }

    @Override
    public void query() {
        System.out.println("校验用户权限的代码");
        System.out.println("查询一条数据");
         System.out.println("记录日志");
    }
}

枚举

枚举
定义枚举类要用关键字enum
所有枚举类都是Enum的子类
枚举类的第一行上必须是枚举项

格式:
- public enum 枚举名 {
- 枚举项1 , 枚举项2 , 枚举项3 .....
- }

常见方法:

    int ordinal()  			返回枚举项的序号
	int compareTo(E o) 		比较两个枚举项的 返回的是两个枚举项序号的 差值
	String name() 			获取枚举项的名称
	String toString()		获取枚举项的名称
	values() 			    获取所有的枚举项
	<T> T valueOf(Class<T> type,String name) 
		用来获取指定的枚举项  
		参数1:枚举类对应的字节码对象 参数2 枚举项的名称

例:
public class MyTest {
    public static void main(String[] args) {
    
        Direction front = Direction.FRONT;
        Direction after = Direction.AFTER;
        Direction left = Direction.LEFT;
        Direction right = Direction.RIGHT;
        System.out.println(front.toString());
        System.out.println(after);
        System.out.println(left);
        System.out.println(right);      
        
    }
}

public enum Direction {
    FRONT("前"), AFTER("后"), LEFT("后"),RIGHT("右"); 
    //下面如果有代码,; 分号不要省略,每个枚举项,用逗号隔开
    private Direction(String name){}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值