Java进阶 1-1 枚举

news2024/11/24 5:20:56

目录

枚举的基本特性

枚举类型中的自定义方法

switch语句中的枚举

编译器创建的values()方法

使用实现代替继承

构建工具:生成随机的枚举

组织枚举

EnumSet

EnumMap


本笔记参考自: 《On Java 中文版》


        枚举类型通过enum关键字定义,其中包含了数量有限的命名变量。

枚举的基本特性

       当我们创建枚举类型时,系统会自动为我们生成一个辅助类,这个类继承自java.lang.Enum。下面的例子展示了其中的一些方法:

【例子:枚举自带的方法】

enum Fruit {
    APPLE,
    BANANA,
    ORANGE
}

public class EnumClass {
    public static void main(String[] args) {
        for (Fruit f : Fruit.values()) {
            System.out.println(
                    f + "对应序数:" + f.ordinal());
            System.out.println(
                    "compareTo(BANANA):" + f.compareTo(Fruit.BANANA));
            System.out.println(
                    "equals(BANANA):" + f.equals(Fruit.BANANA));

            System.out.println("f == Fruit.ORANGE? " +
                    (f == Fruit.ORANGE));
            System.out.println(f.getDeclaringClass());
            System.out.println(f.name());
            System.out.println("====================");
        }
    }
}

        程序执行的结果是:

        简单介绍一些方法:

  • values():生成一个由枚举常量组成的数组,其中常量的顺序和常量声明的顺序保持一致。
  • ordinal():返回一个从0开始的int值,代表每个枚举实例的声明顺序。
  • getDeclaringClass():获得该枚举实例所属的外部包装类。
  • name():返回枚举实例被声明的名称。

    equals()方法由编译器自动生成,而compareTo()方法则来自Comparable接口(Enum实现了它),这里不再赘述。

静态导入枚举类型

        使用枚举类型的理由之一,就是枚举可以增强我们代码的可读性。有时,我们会使用静态导入枚举的方式使用枚举:

【例子:静态导入的枚举类型】

        首先创建一个枚举类型:

// 关于香料的枚举:
public enum SpicinessEnum {
    NOT, MILD, MEDIUM, HOT, FLAMING
}

        现在,让我们在程序中静态导入它:

// 静态导入一个枚举类型:
import static enums.SpicinessEnum.*;

// 制作一个玉米煎饼:
public class Burrito2 {
    SpicinessEnum degree;

    public Burrito2(SpicinessEnum degree) {
        this.degree = degree;
    }

    @Override
    public String toString() {
        return "来个玉米饼,添加香料:" + degree;
    }

    public static void main(String[] args) {
        System.out.println(new Burrito2(NOT));
        System.out.println(new Burrito2(MEDIUM));
        System.out.println(new Burrito2(HOT));
    }
}

        程序执行的结果是:

        通过static import,我们将所有的枚举实例标识符都引入了本地命名空间。值得一提的是,是否静态导入枚举类型大多不会影响代码的运行,但我们仍需要考虑代码的可读性:若代码本身很复杂,静态导入或许就不会是一个更好的选择。

    若枚举定义在通过文件,或定义在默认包中,则无法使用上述的这种方式。

枚举类型中的自定义方法

        除去无法继承,基本上可以将枚举类型看做一个普通的类。可以向其中添加自定义方法,甚至于main()方法。

        通过创建一个含参构造器,枚举可以获取额外的信息,并通过额外的方法来扩展应用。例如:

【例子:在枚举中创建新的方法】

public enum MakeAHuman {
    HEAD("我来组成头部"),
    BODY("我来组成躯体"),
    TONSIL("我来组成扁桃体");
    private String description;

    private MakeAHuman(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    // 也可以进行方法重载:
    @Override
    public String toString() {
        String id = name();
        String lower = id.substring(1).toLowerCase();
        return id.charAt(0) + lower;
    }

    public static void main(String[] args) {
        for (MakeAHuman human : MakeAHuman.values())
            System.out.println(human +
                    ": " + human.getDescription());
    }
}

        程序执行的结果是:

        若想要添加自定义方法,首先必须用分号结束枚举实例的序列。注意:Java会强制我们在枚举中先定义实例

        之前也提到过,枚举类型不允许继承。这意味着枚举在被定义完毕后,无法被用于创建任何新的类型。

switch语句中的枚举

        枚举类型可以被应用于switch语句。一般,switch语句只支持整型或字符串类型,但ordinal()方法可以获取枚举内部的整型序列。在这里,编译器完成了后台的各种工作。

        在通常情况下,若要使用枚举实例,就需要使用枚举的类型名对其进行限定。但在switch语句中不需要这么做:

【例子:switch中的枚举】

enum Signal {
    GREEN, YELLOW, RED
}

public class TrafficLight {
    Signal color = Signal.RED;

    public void change() {
        // 在case语句中,无需使用Signal进行限定:
        switch (color) {
            case RED:
                color = Signal.GREEN;
                break;
            case GREEN:
                color = Signal.YELLOW;
                break;
            case YELLOW:
                color = Signal.RED;
                break;
        }
    }

    @Override
    public String toString() {
        return "现在,信号灯的颜色是:" + color;
    }

    public static void main(String[] args) {
        TrafficLight t = new TrafficLight();
        for (int i = 0; i < 7; i++) {
            System.out.println(t);
            t.change();
        }
    }
}

        程序执行的结果是:

        尽管没有添加default语句,但编译器也没有报错。这不见得是一件好事,因为即使我们注释掉了其中的一条分支,编译器也不会报错:

        因此,在编写分支语句时我们必须小心,确保代码已经覆盖了所有的分支。

编译器创建的values()方法

        根据官方文档的描述,Enum类中并不存在values()方法:

因此我们可以猜测,编译器在后台为我们完成了某件事。接下来的例子会通过反射分析Enum类中的方法:

【例子:通过反射探究Enum类】

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.TreeSet;

enum Explore {
    HERE,
    THERE
}

public class Reflection {
    public static Set<String> analyze(
            Class<?> enumClass) {
        System.out.println("_____分析" + enumClass + "_____");
        System.out.println("$接口:");
        for (Type t : enumClass.getGenericInterfaces())
            System.out.println(t);

        System.out.println("$基类:" +
                enumClass.getSuperclass());

        System.out.println("$方法:");
        Set<String> methods = new TreeSet<>();
        for (Method m : enumClass.getMethods())
            methods.add(m.getName());
        System.out.println(methods);
        return methods;
    }

    public static void main(String[] args) {
        Set<String> exploreMethods =
                analyze(Explore.class);
        System.out.println();
        Set<String> enumMethods =
                analyze(Enum.class);

        System.out.println();
        System.out.println("Explore.containsAll(Enum)? " +
                exploreMethods.containsAll(enumMethods));

        System.out.print("Explore.removeAll(Enum): ");
        exploreMethods.removeAll(enumMethods);
        System.out.println("[" + exploreMethods + "]");


    }
}

        程序执行的结果是:

        从反射的结果可以发现,枚举Explore中多出了Enum没有的values()方法。现在让我们进一步,通过反编译Explore来查看它的内部信息:

反编译告诉我们,values()方法是由编译器添加的一个静态方法。除此之外,还可以发现:Explore内部的valueOf()方法只有一个参数,而Enum自带的valueOf()却有两个参数:

然而,Set只会关注方法名,因此在执行Explore.remove(Enum)后,valueOf()方法也被去除了。

    从反射的结果中,我们还可以知道两件事:① Explore枚举是final类,因此我们无法继承;②反射认为Explore的基类就是Enum,这并不准确,Explore的基类应该是Enum<Explore>,类型擦除使得编译器无法获取完整类型信息,因此才会出现这种现象。

        需要注意的一点是,values()只在子类Explore中存在(由编译器插入),因此当我们将该枚举类型向上转型为Enum时。我们将无法使用这个方法。作为替代,可以使用Class.getEnumConstants()

【例子:getEnumConstants()的使用例】

enum Search {
    HITHER,
    YON
}

public class UpcastEnum {
    public static void main(String[] args) {
        Search[] vals = Search.values();
        Enum e = Search.HITHER; // 发生向上转型
        // e.values(); // 此时会发现Enum中并没有values()方法

        // Class.getEnumConstants()方法返回一个包含枚举中的每个元素的数组
        for (Enum en : e.getClass().getEnumConstants())
            System.out.println(en);
    }
}

        程序执行的结果是:

    因为getEnumConstants()方法属于Class类,因此非枚举类型也可以调用它。不过此时方法会返回null,调用这个结果会抛出异常。

使用实现代替继承

        已知,所有枚举类都会默认继承java.lang.Enum。而Java不支持多重继承,这就意味着一个枚举类无法再继承任何其他的类:

// enum NotPossible extends SomethingElse { ... // 不允许这么做

        作为替代,我们可以令枚举类型实现一些接口:

【例子:让枚举类实现接口】

import java.util.Random;
import java.util.function.Supplier;

enum LetterCharacter
        implements Supplier<LetterCharacter> {
    A, B, C, D, E, F, G;
    private Random rand =
            new Random(47);

    @Override
    public LetterCharacter get() {
        return values()[rand.nextInt(values().length)];
    }
}

public class EnumImplementation {
    public static <T> void printNext(Supplier<T> rg) {
        System.out.print(rg.get() + " ");
    }

    public static void main(String[] args) {
        LetterCharacter ll = LetterCharacter.G;
        for (int i = 0; i < 10; i++)
            printNext(ll);
    }
}

        程序执行的结果是:

        这种做法有一点很奇怪:我们必须传入一个枚举实例,然后才能使用printNext()方法。

构建工具:生成随机的枚举

       为了方便我们使用枚举,可以创建一个用于随机生成枚举的Enums类:

package onjava;

public class Enums {
    private static Random rand = new Random(47);

    public static <T extends Enum<T>> T random(Class<T> ec) {
        return random(ec.getEnumConstants());
    }

    public static <T> T random(T[] values) {
        return values[rand.nextInt(values.length)];
    }
}

        这个类中的random()方法会接收Class对象,并返回随机的枚举对象。

(因为之后也会使用该类,因此在这里提前进行展示)

组织枚举

        尽管枚举类型无法继承,但我们任然会有可能用到继承关系的情况。一般地,继承枚举有两个动机:

  1. 希望扩充原始枚举中的元素。
  2. 想要使用子类型创建不同的子分组。

        一个方法是通过接口对枚举进行分类。下面的例子在接口中将元素分类完毕,然后会基于这个接口生成一个枚举,这样就能实现分类的目的:

【例子:在接口中分类】

public interface Food {
    enum Appetizer implements Food {
        SALAD, SOUP, SPRING_ROLLS;
    }

    enum MainCourse implements Food {
        RICE, NOODLES, BREAD, PASTA;
    }

    enum Dessert implements Food {
        CUPCAKE, JELLY, CANDY, CHOCOLATE, COOKIES;
    }

    enum Drink implements Food {
        COFFEE, TEA, JUICE, MILK
    }
}

        这种方式就像是将枚举作为了接口的子类型一样。通过静态导入,就可以使用它:

import enums.menu.Food;

import static enums.menu.Food.*;

public class TypeOfFood {
    public static void main(String[] args) {
        Food food = Appetizer.SALAD;
        food = MainCourse.RICE;
        food = Dessert.CANDY;
    }
}

        通过这种方法,我们就得到了“由接口组织的枚举”,但它还不足以应对所有情况。当我们需要处理一组类型时,接口并没有内置的方法能够为我们提供便利。此时,使用“由枚举组织的枚举”更为管用:

【例子:由枚举来组织枚举】

import onjava.Enums;

public enum Course {
    APPETIZER(Food.Appetizer.class),
    MAINCOURSE(Food.MainCourse.class),
    DESSERT(Food.Dessert.class),
    COFFEE(Food.Drink.class);

    private Food[] values;

    // 接收枚举类型对应的Class对象
    private Course(Class<? extends Food> kind) {
        values = kind.getEnumConstants();
    }

    public Food randomSelection() {
        return Enums.random(values);
    }
}

         因为Course是一个枚举类型,因此我们可以直接使用枚举特有的方法:

public class Meal {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            for (Course course : Course.values()) {
                Food food = course.randomSelection();
                System.out.println(food);
            }
            System.out.println("======");
        }
    }
}

        程序执行的结果如下:

        Course可以直接调用枚举所有的方法,因此可以很方便地进行遍历操作。

        上述的做法需要使用接口和枚举。显然,可以将它们整理到一起,形成一种更加清晰的写法:

【例子:在枚举中嵌套枚举】

import onjava.Enums;

enum SecurityCategory {
    STOCK(Security.Stock.class),
    BOND(Security.Bond.class);

    Security[] values;

    SecurityCategory(Class<? extends Security> kind) {
        values = kind.getEnumConstants();
    }

    interface Security {
        enum Stock implements Security {
            SHORT, LONG, MARGIN
        }

        enum Bond implements Security {
            MUNICIPAL, JUNK
        }
    }

    public Security randomSelection() {
        return Enums.random(values);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            SecurityCategory category =
                    Enums.random(SecurityCategory.class);
            System.out.println(category + ": " +
                    category.randomSelection());
        }
    }
}

        程序执行的结果是:

        在这种方法中,枚举内部存在一个接口。通过它,我们可以将所需的枚举类型进行聚合。

EnumSet

        Set和枚举都对元素的唯一性有所要求,但枚举无法进行增删操作,因此不如Set来得便利。因此,用于配合枚举的Set类型,EnumSet诞生了。

    EnumSet的一个目的,是替代原本基于int的“位标记”用法。

    这一类型的一大优势就是速度,其内部的实现基于一个long类型的变量(位向量)

        EnumSet中的元素必须来源于某个枚举类型:

【例子:EnumSet的使用】

        为了使用EnumSet,首先需要创建一个枚举(报警器的位置信息):

// 报警感应器的位置
public enum AlarmPoints {
    STAIR1, STAIR2,
    LOBBY,
    OFFICE1, OFFICE2, OFFICE3, OFFICE4,
    BATHROOM,
    UTILITY,
    KITCHEN
}

        利用这个枚举,下面的程序会展示一些EnumSet的基本用法:

import java.util.EnumSet;

import static enums.AlarmPoints.*;

public class EnumSets {
    public static void main(String[] args) {
        // 使用noneOf()方法创建一个空的EnumSet
        EnumSet<AlarmPoints> points =
                EnumSet.noneOf(AlarmPoints.class);

        points.add(BATHROOM);
        System.out.println(points);
        points.addAll(
                EnumSet.of(STAIR1, STAIR2, KITCHEN));
        System.out.println(points);

        System.out.println();
        points = EnumSet.allOf(AlarmPoints.class);
        points.removeAll(
                EnumSet.of(STAIR1, STAIR2, KITCHEN));
        System.out.println(points);
        points.removeAll(
                EnumSet.range(OFFICE1, OFFICE4));
        System.out.println(points);

        System.out.println();
        // complementOf()方法返回points中未包含的枚举集
        points = EnumSet.complementOf(points);
        System.out.println(points);
    }
}

        程序执行的结果是:

        EnumSet.of()方法具有多个重载

这是处于性能的考量。尽管这些of()方法可以被一个使用了可变参数的方法替代,但那样做的效率会略低于现在的这种做法。

    尽管表格上没有出现,但EnumSet中是存在使用可变参数列表的of()方法的。而如果我们只传入一个参数,编译器不会调用这个of()方法,因此也不会产生额外的开销。

        通常情况下,EnumSet是基于64位的long构建的。其中,每个枚举实例需要通过1位来表达其的状态。因此,在使用一个long时,单个EnumSet只能支持包含64个元素的枚举类型。但有时,我们的枚举会超过64个元素:

【例子:超过64个元素的EnumSet

public class BigEnumSet {
    enum Big {
        A1, A2, A3, A4, A5, A6, A7, A8, A9, A10,
        A11, A12, A13, A14, A15, A16, A17, A18, A19, A20,
        A21, A22, A23, A24, A25, A26, A27, A28, A29, A30,
        A31, A32, A33, A34, A35, A36, A37, A38, A39, A40,
        A41, A42, A43, A44, A45, A46, A47, A48, A49, A50,
        A51, A52, A53, A54, A55, A56, A57, A58, A59, A60,
        A61, A62, A63, A64, A65
    }

    public static void main(String[] args) {
        EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);
        System.out.println(bigEnumSet);
    }
}

        程序执行的结果是:

        从输出结果可以看出,若元素超过64个,EnumSet会进行额外的处理。这一点也可以从源代码处了解:

EnumMap

        除了EnumSet,也存在EnumMap。这一特殊的Map要求所有的来自于某个枚举类型。EnumMap内部的实现基于数组,因此有着很高的效率。

    与普通的Map相比,EnumMap在操作上的特殊之处只在于:当我们调用put()方法时,只能使用枚举中的值。

【例子:EnumMap的使用例】

import java.util.EnumMap;
import java.util.Map;

import static enums.AlarmPoints.*;

// 使用了命令模式:
// 创建一个接口(只包含一个方法),衍生出不同的实现
interface Command {
    void action();
}

public class EnumMaps {
    public static void main(String[] args) {
        EnumMap<AlarmPoints, Command> em =
                new EnumMap<>(AlarmPoints.class);
        em.put(KITCHEN,
                () -> System.out.println("厨房失火"));
        em.put(BATHROOM,
                () -> System.out.println("水龙头坏了"));

        for (Map.Entry<AlarmPoints, Command> e :
                em.entrySet()) {
            System.out.println(e.getKey() + ": ");
            e.getValue().action();
        }

        try { // 若不存在指定key值
            em.get(UTILITY).action();
        } catch (Exception e) {
            System.out.println("异常:" + e);
        }
    }
}

        程序执行的结果是:

        在上述的em中,所有的枚举元素都有其对应的键。并且根据输出结果的异常显示,所有的键对应的值都会被初始化为null

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1305184.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring进阶系列丨第五篇】详解Spring中的依赖注入

文章目录 一、说明二、构造函数注入2.1、方式一【index索引方式】2.1.1、定义Bean2.1.2、主配置文件中配置Bean2.1.3、测试 2.2、方式二【indextype组合方式】2.2.1、定义Bean2.2.2、主配置文件配置Bean2.2.3、测试2.2.4、解决方案 2.3、方式三【name方式】2.3.1、定义Bean2.3.…

5. PyTorch——数据处理模块

1.数据加载 在PyTorch中&#xff0c;数据加载可通过自定义的数据集对象。数据集对象被抽象为Dataset类&#xff0c;实现自定义的数据集需要继承Dataset&#xff0c;并实现两个Python魔法方法&#xff1a; __getitem__&#xff1a;返回一条数据&#xff0c;或一个样本。obj[in…

unity Mesh Simplify 1.10(模型优化工具:查看面数,降低面数灯)

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、面板参数详解说明二、使用方法总结 前言 有时候想对模型优化一下&#xff0c;奈何又不会建模方面的。虽然我感觉它的数值不大对&#xff0c;但是不影响我们优化顶点数嘛。 Me…

LeetCode 1631. 最小体力消耗路径:广度优先搜索BFS

【LetMeFly】1631.最小体力消耗路径&#xff1a;广度优先搜索BFS 力扣题目链接&#xff1a;https://leetcode.cn/problems/path-with-minimum-effort/ 你准备参加一场远足活动。给你一个二维 rows x columns 的地图 heights &#xff0c;其中 heights[row][col] 表示格子 (ro…

【玩转TableAgent数据智能分析】TableAgent全功能详解及多领域数据分析实践(中)不同领域数据分析实践

3 电影点评数据分析实践 利用本身自带的电影点评数据&#xff0c;来具体看一下TableAgent的分析能力&#xff0c;选择电影点评数据&#xff0c;智能体会自动导入该数据DMSC20000.csv&#xff0c;大小为3.3 MB。在数据信息展示区&#xff0c;就会显示出该数据&#xff0c;并提供…

你一定要知道的Fiddler过滤器 Filters 详解

如果要对当前Fiddler的抓包进行过滤&#xff08;如过滤掉与测试项目无关的抓包请求&#xff09;&#xff0c;那功能强大的 Filters 过滤器能帮到你。 进入 Filters 选项页&#xff0c;勾选上 Use Filters&#xff0c;即启用过滤器。 Actions 四个选项说明&#xff1a; Run Fi…

SI24R03 高度集成低功耗SOC 2.4G 收发一体芯片

今天给大家介绍一款Soc 2.4G 收发一体模块-SI24R03 Si24R03是一款高度集成的低功耗无线SOC芯片&#xff0c;芯片为QFN32 5x5mm封装&#xff0c;集成了资源丰富的MCU内核与2.4G收发器模块&#xff0c;最低功耗可达1.6uA&#xff0c;极少外围器件&#xff0c;大幅降低系统应用成本…

(第8天)保姆级 PL/SQL Developer 安装与配置

PL/SQL Developer 安装与配置(第8天) 咱们前面分享了很多 Oracle 数据库的安装,但是还没有正式使用过 Oracle 数据库,怎么连接 Oracle 数据库?今天就来讲讲我学习中比较常用的 Oracle 数据库连接工具:PL/SQL DEVELOPER。 PL/SQL Developer 的安装和配置对于新手来说还是…

机器学习---Boosting

1. Boosting算法 Boosting思想源于三个臭皮匠&#xff0c;胜过诸葛亮。找到许多粗略的经验法则比找到一个单一的、高度预 测的规则要容易得多&#xff0c;也更有效。 预测明天是晴是雨&#xff1f;传统观念&#xff1a;依赖于专家系统&#xff08;A perfect Expert) 以“人无…

【Qt信号槽源码分析】

Qt信号槽源码分析 一、相关宏介绍二、示例moc文件源码解析信号发送接收过程源码解析emit signalconnect 三、关键类图&#xff1a;四、时间&空间问题五、总结 一、相关宏介绍 *要使用信号-槽功能&#xff0c;先决条件是继承QObject类&#xff0c;并在类声明中增加Q_OBJECT…

ue5材质预览界面ue 变黑

发现在5.2和5.1上都有这个bug 原因是开了ray tracing引起的&#xff0c;这个bug真是长时间存在&#xff0c;类似的bug还包括草地上奇怪的影子和地形上的影子等等 解决方法也很简单&#xff0c;就是关闭光追&#xff08;不是…… 就是关闭预览&#xff0c;在材质界面preview sc…

屠宰加工污废水处理工艺设备有哪些

屠宰加工行业对于废水处理的要求日益严格&#xff0c;为了达到环保要求&#xff0c;减少对环境造成的负面影响&#xff0c;屠宰加工污废水处理工艺设备应运而生。以下是常见的几种工艺设备&#xff1a; 1. 沉淀池&#xff1a;沉淀池是屠宰加工废水处理中常用的处理设备之一。废…

【RTOS学习】模拟实现任务切换 | 寄存器和栈的变化

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3c0;认识任务切换&#x1f3d0;切换的实质&#x1f3d0;栈中的内容&#x1f3d0;切…

scala表达式

1.8 表达式&#xff08;重点&#xff09; # 语句(statement)&#xff1a;一段可执行的代码# 表达式(expression)&#xff1a;一段可以被求值的代码&#xff0c;在Scala中一切都是表达式 - 表达式一般是一个语句块&#xff0c;可包含一条或者多条语句&#xff0c;多条语句使用“…

Fiddler如何比较两个接口请求?我来告诉你

进行APP测试时&#xff0c;往往会出现Android和iOS端同一请求&#xff0c;但执行结果不同&#xff0c;这通常是接口请求内容差异所致。 我习惯于用Fiddler抓包&#xff0c;那此时应该如何定位问题呢&#xff1f; 分别把Android和iOS的接口请求另存为TXT文件&#xff0c;然后用…

软件安全设计

目录 一&#xff0c;STRIDE 威胁建模 1&#xff0c;STRIDE 2&#xff0c;总体流程&#xff08;关键步骤&#xff09; 3&#xff0c;数据流图的4类元素 二&#xff0c;安全设计原则 三&#xff0c;安全属性 一&#xff0c;STRIDE 威胁建模 1&#xff0c;STRIDE STRIDE 是…

区块链实验室(32) - 下载arm64的Prysm

Prysm是Ethereum的共识层。 1. 下载prysm.sh curl https://raw.githubusercontent.com/prysmaticlabs/prysm/master/prysm.sh --output prysm.sh && chmod x prysm.sh2. 下载x86版prysm共识客户端 ./prysm.sh beacon-chain --download-only3.下载arm64版prysm共识客…

论文解读:Medical Transformer论文创新点解读

这篇文章其实就是基于Axial-DeepLab: Stand-Alone Axial-Attention forPanoptic Segmentation论文上进行的一些小创新 Stand-Alone Axial-Attention forPanoptic Segmentation论文解读&#xff1a; 论文解读&#xff1a;Axial-DeepLab: Stand-Alone Axial-Attention forPanop…

K8s可视化kuboard 部署

创建资产 [rootkube-master ~]# kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml 查看对应资源 [rootkube-master ~]# kubectl get pod -n kuboard NAME READY STATUS RESTARTS AGE kuboard-agent-2-5c4f886…

InnoDB在SQL查询中的关键功能和优化策略

文章目录 前言存储引擎介绍存储引擎是干嘛的InnoDB的体系结构 InnoDB的查询操作InnoDB的查询原理引入 Buffer Pool引入数据页Buffer Pool 的结构数据页的加载Buffer Pool 的管理Buffer Pool 的优化 总结 前言 通过上篇文章《MySQL的体系结构与SQL的执行流程》了解了SQL语句的执…