数据结构的学习历程13_myenums==letters

		* [反射的优缺点](#_107)
+ [枚举](#_114)
+ - * [枚举的定义](#_119)
		* [枚举的常用方法](#_146)
+ [枚举是否可以反射](#_176)
+ [单例模式(了解)](#_180)
+ [Lambda表达式](#Lambda_220)
+ - * [函数式接口](#_226)
		* [用法](#_231)
		* [举例](#_264)

反射

在java中,通过编译会生成一个.class的字节码文件,在使用java命令来运行java文件的时候,第一步java.exe启动JVM,第二步JVM启动类加载器,第三步类加载器加载对应类,类加载器有三种,分别是:
Boot Strap Class Loader 启动类加载器
Extension Class Loader
Application Class Loader 自定义类
这里会采用双亲委派模型来加载类,加载成功后就变成了一个Class对象,而这个对象中存储的就是当前类的信息。
而下一步就会进入一个链接的环节:链接指的是将Java类的二进制代码合并到JVM的运行状态之中的过程,这个过程包含验证、准备、解析等几个步骤,验证用来确保java类的二进制表示在结构上是正确的,如果出现错误,则会抛出异常。准备过程是建造java类的静态域,并将这些域的值设置为默认值,而解析的过程是确保java类引用 的其他类,包括接口,父类,方法的形参,返回值等能够被正确的寻找到,解析的过程可能会导致其他的java类被加载。
当一个java类第一次被真正使用时,JVM会进行该类的初始化操作。初始化过程的主要操作时执行静态代码块和初始化静态域。且其父类也会被初始化(接口的父类不需要初始化)
java的反射是指在运行状态中,对于任意一个类,都能知道这个类的所有方法与属性;对于任意一个对象,都能够调用这个类的方法与属性。
Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型
反射中重要的几个类型:
Class 代表类的实体,表示类或接口
Filed 表示类的成员变量
Method 表示类的方法
Constructor 表示类的构造方法

获得Class对象的方法

如果要进行反射,那么就需要拿到一个当前需要反射的类的一个对象,通过这个对象的核心方法,达到反射的目的。
而获取Class的方法有三种:
首先写一个要操作的类:(自定义类,没有要求)

package reflect;
class Picture{
    private String name = "lit";
    public String color = "black";
    Picture() {
        System.out.println(name+color);;
    }
    private Picture (String name ,String color){
        this.color = color;
        this.name = name;
        System.out.println(name+color);
    }
    private void func (){
        System.out.println("这是一个func方法");
    }
        @Override
    public String toString() {
        return "Picture{" + "name='" + name + '\'' + ", color=" + color + '}';
    }
}

使用类对象的getClass()方法

	Picture p1 = new Picture();
    Class c1 = p1.getClass();

使用.class方法
适合在编译前就已经明确要操作的class

	Class c2 = Picture.class;

使用Class.forName(“类的全路径名”);静态方法
适合确定了要操作的类的全路径

    try {
        Class c3 = Class.forName("reflect.Picture");//这里的Picture是需要操作的类的全路径,如果有包,则需要加上包的路径
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

反射的使用

class的对象获取到了,接下来就该反射了,这里要注意的是,所有与反射相关的包都在import java.lang.reflect这个路径下。
反射调用私有的构造方法:

        try {
            Class<?> cl = Class.forName("reflect.Picture");
            //加了Declared就是不仅可以调用公开的,也可以调用私有的
            Constructor<?> constructor = cl.getDeclaredConstructor(String.class,String.class);//后面的参数是需要操作的构造方法的参数
            //cl.getConstructor();
            constructor.setAccessible(true);//修改访问权限
            Object obj = constructor.newInstance("abcd","white");//传值
            Picture pic = (Picture) obj;
            System.out.println(pic);
        }catch (Exception e){
            e.printStackTrace();
        }

反射修改私有的属性:

        try {
            Class<?> cl = Class.forName("reflect.Picture");
            //加了Declared就是不仅可以调用公开的,也可以调用私有的
            Field field = cl.getDeclaredField("name");//此处填要操作的属性的变量名
            field.setAccessible(true);//修改访问权限
            Object obj = cl.newInstance();//传值
            Picture pic = (Picture) obj;
            field.set(pic,"what");
            System.out.println(pic);
        }catch (Exception e){
            e.printStackTrace();
        }

反射调用私有方法:

        try {
            Class<?> cl = Class.forName("reflect.Picture");
            Method method = cl.getDeclaredMethod("func");//无参,则只需要传入一个String类型的方法名,有参数则在后面加参数类型.class
            method.setAccessible(true);
            Object obj = cl.newInstance();
            Picture pic = (Picture) obj;
            method.invoke(pic);
        }catch (Exception e){
            e.printStackTrace();
        }

反射的优缺点

反射的优点:
对于任意一个类,通过反射都能获取这个这个类的任意方法或属性,对于任何一个对象,通过反射可以调用这个对象堆所有方法,也可修改这个对象的所有属性
增加程序的灵活性、扩展性,降低耦合性
反射的缺点:
有效率问题,会导致程序效率降低
因为绕过了源代码,所以会带来相应的维护问题

枚举

将一组常量组织起来进行统一管理
在java中,枚举实际上就是一个类,但是,枚举的构造方法默认是私有的
优点:更简单,安全,有内置方法,代码更优雅,可避免反射和序列化问题
缺点:不可继承,无法扩展

枚举的定义

枚举是可以使用switch语句的:

public enum MyEnum {
    dog,cat,pig,sheep;
    public static void main(String[] args) {
        MyEnum myEnum = MyEnum.cat;
        switch (myEnum){
            case cat:
                System.out.println("cat");
                break;
            case dog:
                System.out.println("dog");
                break;
            case pig:
                System.out.println("pig");
                break;
            case sheep:
                System.out.println("sheep");
                break;
            default:
                System.out.println("null");
                break;
        }
    }
}

枚举的常用方法

values()以数组形式返回枚举类型的所有成员

    public static void main(String[] args) {
        MyEnum[] myEnums = MyEnum.values();//以数组形式返回枚举类型的所有成员
    }

ordinal()获取枚举成员的索引位置

    public static void main(String[] args) {
        for (int i = 0; i <myEnums.length ; i++) {
            System.out.println(myEnums[i] + " " + myEnums[i].ordinal());//获取枚举成员的索引位置
        }
    }

valueOf()将普通字符串转换为枚举实例

    public static void main(String[] args) {
		System.out.println(MyEnum.valueOf("cat"));//大小写敏感
	}

compareTo()比较两个枚举成员在定义时的顺序

    public static void main(String[] args) {
        MyEnum myEnums1 = MyEnum.sheep;
        MyEnum myEnums2 = MyEnum.pig;


# 最后

金三银四马上就到了,希望大家能好好学习一下这些技术点

学习视频:

![](https://img-blog.csdnimg.cn/img_convert/65ec5df3b0bcf1b7311dfe32b7e8b866.webp?x-oss-process=image/format,png)

大厂面试真题:

![](https://img-blog.csdnimg.cn/img_convert/a922aebf768e3dedaf1a8031eb605ef6.webp?x-oss-process=image/format,png)

    public static void main(String[] args) {
        MyEnum myEnums1 = MyEnum.sheep;
        MyEnum myEnums2 = MyEnum.pig;


# 最后

金三银四马上就到了,希望大家能好好学习一下这些技术点

学习视频:

[外链图片转存中...(img-1dHDZFXV-1714722910382)]

大厂面试真题:

[外链图片转存中...(img-WUEWAQxp-1714722910383)]

> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值