Effective第三版 中英 | 第2章 创建和销毁对象 | 考虑静态工厂方法而不是构造函数

news2024/11/24 18:29:45

文章目录

  • Effective第三版
    • 第2章 创建和销毁对象
      • 前言
      • 考虑静态工厂方法而不是构造函数

Effective第三版

第2章 创建和销毁对象

在这里插入图片描述

前言

大家好,这里是 Rocky 编程日记 ,喜欢后端架构及中间件源码,目前正在阅读 effective-java 书籍。同时也把自己学习该书时的笔记,代码分享出来,供大家学习交流,如若笔记中有不对的地方,那一定是当时我的理解还不够,希望你能及时提出。如果对于该笔记存在很多疑惑,可以先去翻阅《Java核心技术》也欢迎和我交流讨论,最后也感谢您的阅读,点赞,关注,收藏~

前人述备矣,我只是知识的搬运工,effective 书籍源码均在开源项目 java-diary 中的 code-effective-third 模块中

源代码仓库地址: https://gitee.com/Rocky-BCRJ/java-diary.git

考虑静态工厂方法而不是构造函数

  The traditional way for a class to allow a client to obtain an instance is to provide a public constructor. There is another technique that should be a part of every programmer’s toolkit. A class can provide a public static factory method, which is simply a static method that returns an instance of the class. Here’s a simple example from Boolean(the boxed primitive class for boolean). This method translates a boolean primitive value into a Boolean object reference:

  类允许客户端获取实例的传统方法是提供公共构造器。还有一种技术应该是每个程序猿的工具箱的一部分。一个类可以提供一个公共静态工厂方法,它仅仅是一个返回类实例的静态方法。下面是布尔(基本类型 boolean 的包装类)的一个简单示例。这个方法将一个布尔原始值转换成布尔对象引用:

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

  Note that a static factory method is not the same as the Factory Method pattern from Design Patterns[Gamma95]. The static factory method described in this item has no direct equivalent in Design Patterns.

  注意:静态工厂方法与设计模式 [Gamma95] 的工厂方法模式不同,在该项中描述的静态工厂方法并不等同于设计模式中的工厂方法模式。

  A class can provide its clients with static factory methods instead of, or in addition to, public constructors. Providing a static factory method instead of a public constructor has both advantages and disadvantages.

  一个类可以为其客户提供静态工厂方法,而不是公共构造函数。提供静态工厂方法而不是公共构造函数既有优点也有缺点。

  One advantage of static factory methods is that, unlike constructors, they have names. If the parameters to a constructor do not, in and of themselves, describe the object being returned, a static factory with a well-chosen name is easier to use and the resulting client code easier to read. For example, the constructor BigInteger(int, int, Random), which returns a BigInteger that is probably prime, would have been better expressed as a static factory method named BigInteger.probablePrime. (This method was added in Java4.)

  静态工厂方法的一个优点是,它们是有名称的,而构造函数的名称都是一样的。如果构造函数的参数本身不能描述返回的对象,那么使用一个精心命名的静态工厂更容易使用,并且生成的客户端代码更容易阅读。例如BigInteger的一个构造函数:BigInteger(int, int, Random),这个构造函数返回一个BigInteger有可能是一个质数,使用一个精心命名的静态工厂方法会更容易描述该方法返回的 BigInteger 类型,比如BigInteger.probablePrime(这是在 Java 4 中添加的)。

  A class can have only a single constructor with a given signature. Programmers have been known to get around this restriction by providing two constructors whose parameter lists differ only in the order of their parameter types. This is a really bad idea. The user of such an API will never be able to remember which constructor is which and will end up calling the wrong one by mistake. People reading code that uses these constructors will not know what the code does without referring to the class documentation.

  一个类只能有一个带有给定签名的构造函数。程序猿可以通过提供两个构造函数来绕过这个限制,这些构造函数的参数列表只在参数类型的顺序上有所不同。这是个相当坏的主意。这样使用这个 API 的用户永远无法记住应该使用哪个构造函数,并且最终会调用错误的构造函数。使用这些构造函数的人在不阅读引用类文档的情况下是不知道代码是干什么的。

  Because they have names, static factory methods don’t share the restriction discussed in the previous paragraph. In cases where a class seems to require multiple constructors with the same signature, replace the constructors with static factory methods and carefully chosen names to highlight their differences.

  因为静态工厂方法有名称,所以就不会有这个限制,在一个类需要使用多个签名、多个构造函数的情况下,用静态工厂方法代替构造函数,并仔细选择方法的名称就可以突出构造函数之间的差异了。

  A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked. This allows immutable classes (Item 17) to use preconstructed instances, or to cache instances as they’re constructed, and dispense them repeatedly to avoid creating unnecessary duplicate objects.

  静态工厂方法的第二个优点是,与构造函数不同,它们不需要在每次被调用时创建一个新对象。这允许不可变类(第 17 项)使用预先构造的实例,或者在构建时缓存实例,并重复分发它们,以避免创建不必要的重复对象。

  The Boolean.valueOf(boolean) method illustrates this technique: it never creates an object. This technique is similar to the Flyweight pattern [Gamma95]. It can greatly improve performance if equivalent objects are requested often, especially if they are expensive to create.

  Boolean.valueOf(boolean)方法使用了这种方式:它从不创建对象。这种技术类似于享元模式[Gamma95]。如果经常请求等效对象,特别是当它们的创建成本很高时,它可以极大地提高性能。

  The ability of static factory methods to return the same object from repeated invocations allows classes to maintain strict control over what instances exist at any time. Classes that do this are said to be instance-controlled.There are several reasons to write instance-controlled classes. Instance control allows a class to guarantee that it is a singleton (Item 3) or noninstantiable (Item 4). Also, it allows an immutable value class (Item 17) to make the guarantee that no two equal instances exist: a.equals(b) if and only if a == b*.* This is the basis of the Flyweight pattern [Gamma95]. Enum types (Item 34) provide this guarantee.

  静态工厂方法从重复调用中返回相同的对象的能力允许类在任何时候保持对实例的严格控制。这样做的类被认为是实例控制的。编写实例控制类的原因有几个。实例控制允许一个类保证它是一个单例(第 3 项)或非实例化的(第 4 项),并且它允许一个不可变的值类(第 17 项)来保证没有两个相等的实例存在:当且仅当a==b成立时,a.equals(b)返回true,这是享元模式 [Gamma95] 的基础,枚举类型就提供了这种保证。

  A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type. This gives you great flexibility in choosing the class of the returned object.

  静态工厂方法的第三个优点是,与构造函数不同,它们返回的对象可以是返回类型的任何子类的实例对象。这使在选择返回的对象的类时具有很大的灵活性。

  One application of this flexibility is that an API can return objects without making their classes public. Hiding implementation classes in this fashion leads to a very compact API. This technique lends itself to interface-based frameworks(Item 20), where interfaces provide natural return types for static factory methods.

  这种灵活性的一个应用是,API 可以返回对象,同时又不会使对象的类变成公有的,以这种方式隐藏实现类会使 API 变得非常简洁。这种技术适用于基于接口的框架(interface-based frameworks,见第 20 项),因为在这种框架中,接口为静态工厂方法提供了自然返回类型。

  Prior to Java 8, interfaces couldn’t have static methods. By convention, static factory methods for an interface named Type were put in a noninstantiable companion class(Item 4) named Types. For example, the Java Collections Framework has forty-five utility implementations of its interfaces, providing unmodifiable collections, synchronized collections, and the like. Nearly all of these implementations are exported via static factory methods in one noninstantiable class (java.util.Collections). The classes of the returned objects are all nonpublic.

  在 Java 8 之前,接口不能有静态方法。按照惯例,名为 Type 的接口的静态工厂方法被放置在一个不可实例化的名为 Types 的配套类(noninstantiable companion class)(第 4 项)中。例如,Java Collections Framework 有 45 个便利实现,分别提供了不可修改的集合、同步集合等等。几乎所有这些实现都通过静态工厂方法在一个不可实例化的类(java.util.Collections)中导出。所有返回对象的类都是非公有的。

    The Collections Framework API is much smaller than it would have been had it exported forty-five separate public classes, one for each convenience implementation. It is not just the bulk of the API that is reduced but the conceptual weight:the number and difficulty of the concepts that programmers must master in order to use the API. The programmer knows that the returned object has precisely the API specified by its interface, so there is no need to read additional class documentation for the implementation class. Furthermore, using such a static factory method requires the client to refer to the returned object by interface rather than implementation class, which is generally good practice (Item 64).

  现在的 Collections Framework API 比导出的 45 个独立的公有类的那种实现方式要小得多,每种便利的实现都对应一个类。这不仅仅减少了 API 的数量,还包括概念上的权重:程序猿必须掌握的概念的数量和难度,以便使用 API。程序猿知道返回的对象正好有其接口指定的 API,因此不需要为实现类去阅读额外的类文档。此外,这种工厂方法要求客户端通过接口而不是实现类来引用返回的对象,这通常是很好的实践方式(第 64 项)。

  As of Java 8, the restriction that interfaces cannot contain static methods was eliminated, so there is typically little reason to provide a noninstantiable companion class for an interface. Many public static members that would have been at home in such a class should instead be put in the interface itself. Note, however, that it may still be necessary to put the bulk of the implementation code behind these static methods in a separate package-private class. This is because Java 8 requires all static members of an interface to be public. Java 9 allows private static methods, but static fields and static member classes are still required to be public.

  从 Java 8 开始,消除了接口不能包含静态方法的限制,因此通常没有理由为接口提供不可实例化的伴随类。许多公共静态成员应该放在接口本身中。但请注意,可能仍有必要将大量实现代码放在这些静态方法后面的单独的包私有类中。这是因为 Java 8 要求接口的所有静态成员都是公共的。Java 9 允许私有静态方法,但静态字段和静态成员类的属性依然是要求是公共的。

  A fourth advantage of static factories is that the class of the returned object can vary from call to call as a function of the input parameters. Any subtype of the declared return type is permissible. The class of the returned object can also vary from release to release.

  静态工厂方法的第四个优点是,静态工厂方法所返回的对象的类可以随着每次调用而变化,这取决于静态工厂方法的参数值。只要返回的类型是声明的类的子类都是允许的。返回对象的类也可能随着发行版本的不同而不同。

  The EnumSet class (Item 36) has no public constructors, only static factories. In the OpenJDK implementation, they return an instance of one of two subclasses, depending on the size of the underlying enum type: if it has sixty-four or fewer elements, as most enum types do, the static factories return a RegularEnumSet instance, which is backed by a single long; if the enum type has sixty-five or more elements, the factories return aJumboEnumSet instance, backed by a long array.

  在EnumSet类(第 36 项)中没有公有的构造方法,只有静态工厂方法。在 OpenJDK 实现中的,它们返回两个子类之一的实例,具体取决于基础枚举类型的大小:如果它有 64 个或更少的元素,就像大多数枚举类型所做的那样,静态工厂返回一个RegularEnumSet实例, 它由单个long的支持;如果枚举类型有 65 个或更多元素,则工厂将返回一个由长数组支持的JumboEnumSet实例。

  The existence of these two implementation classes is invisible to clients. If RegularEnumSet ceased to offer performance advantages for small enum types, it could be eliminated from a future release with no ill effects. Similarly, a future release could add a third or fourth implementation of EnumSet if it proved beneficial for performance. Clients neither know nor care about the class of the object they get back from the factory; they care only that it is some subclass of EnumSet.

  这两个实现类的存在对于客户端是不可见的。如果 RegularEnumSet 不再为小枚举类型提供性能优势可以从未来版本中删除,没有任何不良影响。 同样,未来如果证明有利于性能,则可以添加EnumSet的第三或第四个实现。客户即不知道也不关心他们从工厂中获取的对象的类型,他们只关心它是EnumSet的一些子类。

  A fifth advantage of static factories is that the class of the returned object need not exist when the class containing the method is written. Such flexible static factory methods form the basis of service provider frameworks, like the Java Database Connectivity API (JDBC). A service provider framework is a system in which providers implement a service, and the system makes the implementations available to clients, decoupling the clients from the implementations.

  静态工厂方法的第五个优点是,返回的对象所属的类,在编写包含该静态工厂方法的类时可以不必存在。这种灵活的静态工厂方法构成了服务提供者框架(Service Provider Framework)的基础,例如 JDBC(Java 数据库连接,Java Database Connectivity)API。服务提供者框架是提供者实现服务的系统,系统使实现可用于客户端,将客户端与实现分离【微服务】。

  There are three essential components in a service provider framework: a service interface, which represents an implementation; a provider registration API, which providers use to register implementations; and a service access API, which clients use to obtain instances of the service. The service access API may allow clients to specify criteria for choosing an implementation. In the absence of such criteria, the API returns an instance of a default implementation, or allows the client to cycle through all available implementations. The service access API is the flexible static factory that forms the basis of the service provider framework.

  服务提供者框架中有三个基本组件:服务接口【提供者】,代表一个实现;提供者注册 API【注册中心】,提供者用于注册实现;以及服务访问 API【消费者】,客户端使用它来获取服务的实例。服务访问 API 可以允许客户端指定用于选择实现的标准。 如果没有这样的标准,API 将返回默认实现的实例,或允许客户端循环遍历所有可用的实现。服务访问 API 是灵活的静态工厂,它构成了服务提供者框架的基础。

  An optional fourth component of a service provider framework is a service provider interface, which describes a factory object that produce instances of the service interface. In the absence of a service provider interface, implementations must be instantiated reflectively (Item 65). In the case of JDBC, Connection plays the part of the service interface, DriverManager.registerDriver is the provider registration API, DriverManager.getConnection is the service access API, and Driver is the service provider interface.

  服务提供者框架的可选第四个组件是服务提供者接口,它描述了生成服务接口实例的工厂对象。在缺少服务提供者接口的情况下,必须反复实例化实现(第 65 项)。对于 JDBC,Connection 扮演服务接口的一部分,DriverManager.registerDriver 是提供者注册 API,DriverManager.getConnection 是服务访问 API,Driver 是服务提供者接口。

  There are many variants of the service provider framework pattern. For example, the service access API can return a richer service interface to clients than the one furnished by providers. This is the Bridge pattern [Gamma95]. Dependency injection frameworks (Item 5) can be viewed as powerful service providers. Since Java 6, the platform includes a general-purpose service provider framework, java.util.ServiceLoader, so you needn’t, and generally shouldn’t, write your own (Item 59). JDBC doesn’t use ServiceLoader, as the former predates the latter.

  服务提供者框架模式有许多变体。例如,服务访问 API 可以向客户端返回比提供者提供的服务接口更丰富的服务接口。这是桥接模式 [Gamma95] 。依赖注入框架(第 5 项)可视为强大的服务提供者。从 Java 6 开始,该平台包含一个通用服务提供程序框架 java.util.ServiceLoader,因此你不需要(通常不应该)自己编写(第 59 项)。JDBC 不使用 ServiceLoader,因为前者早于后者。

  The main limitation of providing only static factory methods is that classes without public or protected constructors cannot be subclassed. For example, it is impossible to subclass any of the convenience implementation classes in the Collections Framework. Arguably this can be a blessing in disguise because it encourages programmers to use composition instead of inheritance (Item 18), and is required for immutable types (Item 17).

  静态工厂方法的主要限制在于,类如果不含公有的或者受保护的构造器,就不能被子类化。例如:不可能将 Collections Framework 中的任何方便的实现类子类化。但是这也许会因祸得福,因为它鼓励程序猿使用组合,而不是继承(第 18 项),并且要求必须是不可变的(第 17 项)。

  A second shortcoming of static factory methods is that they are hard for programmers to find. They do not stand out in API documentation in the way that constructors do, so it can be difficult to figure out how to instantiate a class that provides static factory methods instead of constructors. The Javadoc tool may someday draw attention to static factory methods. In the meantime, you can reduce this problem by drawing attention to static factories in class or interface documentation and by adhering to common naming conventions. Here are some common names for static factory methods. This list is far from exhaustive:

  静态工厂方法的第二个缺点是程序猿很难找到它们。它们不像构造函数那样在 API 文档中脱颖而出,因此很难弄清楚如何实例化提供静态工厂方法而不是构造函数的类。Javadoc 工具有一天可能会引起对静态工厂方法的注意。在此期间,你可以通过引起对类或接口文档中的静态工厂的注意并遵守常见的命名约定来减少此问题。以下是静态工厂方法的一些常用名称。 这份清单远非详尽无遗:

  • from—A type-conversion method that takes a single parameter and returns a corresponding instance of this type, for example:

    from:一种类型转换方法,它接受单个参数并返回此类型的相应实例,

    例如:Date d = Date.from(instant);

  • of—An aggregation method that takes multiple parameters and returns an instance of this type that incorporates them, for
    example:

    of:一种聚合方法,它接受多个参数并返回包含它们的此类型的实例,

    例如:Set faceCards = EnumSet.of(JACK, QUEEN, KING);

  • valueOf—A more verbose alternative to from and of, for example:

    valueOf:一个更详细的替代方案,

    例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

  • instance or getInstance—Returns an instance that is described by its parameters (if any) but cannot be said to have the same value, for example:

    instance or getInstance:返回由其参数(如果有)描述的实例,但不能说它具有相同的值,

    例如:StackWalker luke = StackWalker.getInstance(options);

  • create or newInstance—Like instance or getInstance, except that the method guarantees that each call returns a new instance, for example:

    create or newInstance:与 instance 或 getInstance 类似,不同之处在于该方法保证每个调用都返回一个新实例,

    例如:Object newArray = Array.newInstance(classObject, arrayLen);

  • getType—Like getInstance, but used if the factory method is in a different class. Type is the type of object returned by the factory method, for example:

    getType:与 getInstance 类似,是在工厂方法位于不同的类中时使用它。Type 指的是工厂方法返回的对象类型,

    例如:FileStore fs = Files.getFileStore(path);

  • newType—Like newInstance, but used if the factory method is in a different class. Type is the type of object returned by the factory method, for example:

    newType:与 newInstance 类似,是在工厂方法位于不同的类中时使用它。Type 指的是工厂方法返回的对象类型,例如:BufferedReader br = Files.newBufferedReader(path);

  • type—A concise alternative to getType and newType, for example:

    type:获取 Type 和 new Type 一个简明替代的方法,

    例如:List<Complaint> litany = Collections.list(legacyLitany);

  In summary, static factory methods and public constructors both have their uses, and it pays to understand their relative merits. Often static factories are preferable, so avoid the reflex to provide public constructors without first considering static factories.

  总之,静态工厂方法和公共构造函数都有它们的用途,理解它们的相对优点是值得的。通常静态工厂是优选的,不要在第一反应就是使用构造函数,应当先考虑使用静态工厂方法。

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

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

相关文章

基于SSM的人才招聘网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

模拟实现库函数:strcpy

目录 通过cplusplus网站了解函数功能&#xff1a; 断言assert的使用&#xff1a; 关于const&#xff1a; 本篇你最应该了解的内容&#xff1a; 通过cplusplus网站了解函数功能&#xff1a; 要模拟实现库函数&#xff0c;首先我们需要了解这个函数的参数&#xff0c;函数的…

主机加固介绍

最近公司做服务器安全&#xff0c;开始在市场了解产品&#xff0c;对这一块算是短暂的研究了一段时间&#xff0c;有一点心得给大家分享一下。 主机加固 最近主机加固的概念被炒得火热&#xff0c;主机加固的功能也正在被致力于服务器安全的相关人士所关注。 那么究竟什么是主…

【CVPR2022】CSWin Transformer详解

【CVPR2022】CSWin Transformer详解 0. 引言1. 网络结构2. 创新点2.1 Cross-Shaped Window Self-Attention2.2 Locally-Enhanced Positional Encoding(LePE) 3. 实验总结 0. 引言 Transformer设计中一个具有挑战性的问题是&#xff0c;全局自注意力的计算成本非常高&#xff0…

chatgpt赋能python:Python代码怎么敲:了解Python编程语言

Python代码怎么敲&#xff1a;了解Python编程语言 Python是一种高级编程语言&#xff0c;具有易读易用和高效性等优点。这使得Python成为了程序员的最佳选择&#xff0c;并成为了广泛应用于机器学习、Web开发、数据分析等领域。 Python代码敲法&#xff1a;小技巧 Python代码…

chatgpt赋能python:Python主要语句介绍

Python主要语句介绍 Python是一种广泛使用的高级编程语言&#xff0c;其语法简介、易于学习&#xff0c;并有丰富的库和工具支持。在Python中&#xff0c;主要的语句可以帮助开发人员快速编写代码&#xff0c;实现各种各样的任务。在本文中&#xff0c;我们将介绍Python中的主…

性能优化之高Log file sync等待实战案例分享

故障情况 AWR报告如下&#xff1a; 之后他们把大部分业务停掉后&#xff0c;Log file sync等待事件还是非常高。 通过对比昨天跟今天相同时间的AWR&#xff0c;在业务量小非常多的情况&#xff0c;等待时间还是高非常大。 诊断过程 log file sync等待事件首先判断当前系统IO…

“微商城”项目(1环境搭建)

开发工具分享&#xff1a; 百度网盘&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1lSsCjf-_zx1ymu6uZeG26Q?pwdhuan 提取码&#xff1a;huan 一、环境搭建说明 本项目服务端环境要求为 Windows Apache PHP MySQL。 下面介绍如何搭建环境&#xff0c;部署服…

CW32系列模数转换器(ADC)

模数转换器&#xff08;ADC&#xff09;的主要功能是将模拟量转换为数字量&#xff0c;方便MCU进行处理。下面以CW32L083为例介绍CW系列的模数转换器的特点和功能&#xff0c;并提供演示实例。 一、概述 CW32L083 内部集成一个 12 位精度、最高 1M SPS 转换速度的逐次逼近型模…

位操作符的应用

目录 位操作符的概念&#xff1a; 一、&&#xff08;按位与&#xff09;&#xff1a;两个整数的补码对应的二进制位有0则为0&#xff0c;两个同时为1才为1&#xff0c;得到的数仍为补码。 二、|&#xff08;按位或&#xff09;&#xff1a;两个整数的补码对应的二进制位…

Effective第三版 中英 | 第2章 创建和销毁对象 | 当面临多个参数的构造器时考虑使用构建器

文章目录 Effective第三版前言第2章 创建和销毁对象当面临多个参数的构造器时考虑使用构建器 Effective第三版 前言 大家好&#xff0c;这里是 Rocky 编程日记 &#xff0c;喜欢后端架构及中间件源码&#xff0c;目前正在阅读 effective-java 书籍。同时也把自己学习该书时的笔…

【KKT】∇f(x)+λ∇g(x)=0中λ的讨论

Karush-Kuhn-Tucker (KKT)条件 〇、问题背景 在阅读 Karush-Kuhn-Tucker (KKT)条件 时&#xff0c;不太能理解 ∇ f \nabla f ∇f 的方向&#xff0c;以及 ∇ g \nabla g ∇g 的方向&#xff1a; 为什么 ∇ f \nabla f ∇f 是指向可行域内部&#xff0c; ∇ g \nabla g ∇g…

Java多线程方面知识

目录 1.程序、进程、线程 2.进程与线程的内存解析 3.并发与并行 4.Java程序的线程 5.多线程的创建&#xff1a;方式一&#xff1a;继承于Thread类 6.start方法的作用 7.使用start()时要注意的问题 8.Thread类中的一些方法 9.线程的优先级 10.多线程的创建&#xff1a…

【JAVA】清缓存(打断点删除 / 新增表或字段无效)

一. 打断点无效 情景 新写了一个获取列表数据接口&#xff0c;前端调用的&#xff0c;获取到的数据为空数组。在数据库中查看&#xff0c;是有数据的&#xff0c;但是调用接口返回数据为空。接下来就打断点啦&#xff0c;发现无效&#xff01;表现如下 没有可执行的…

【Bio】牙的分类

文章目录 IncisorCentral IncisorLateral Incisor Canine / CuspidPremolarFirst PremolarSecond Premolar MolarFirst MolarSecond MolarThird Molar / Wisdom Tooth Ref Incisor Central Incisor Lateral Incisor Canine / Cuspid Premolar First Premolar Second Prem…

第六十二天学习记录:C语言进阶:C语言预处理2

带副作用的宏参数 当宏参数在宏的定义中出现超过一次的时候&#xff0c;如果参数带有副作用&#xff0c;那么你在使用这个宏的时候就可能出现危险&#xff0c;导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。例如&#xff1a; x1;//不带副作用 x;//带有副作…

安全认证:

1. 认证概述 为什么要有认证&#xff1f; 防止非法路由器接入企业内网的ospf路由器&#xff0c;保护内网安全 2. 认证方式 认证方式分为接口认证和区域认证&#xff0c;接口认证和区域认证没有本质的区别&#xff0c;接口认证是当区域内链路过多的情况下&#xff0c;接口认证…

Java网络开发(Tomcat)—— Servlet学习 Web相关背景知识 JavaWeb项目初步

本文目录 引出一、软件架构BS和CS二、实现Web服务的条件和步骤三、Tomcat搭建Web项目初步1.pom.xml文件配置2.web.xml文件更新3.Tomcat运行环境配置4.项目文件层级解析 四、JavaWeb项目文件分类&#xff08;1&#xff09;静态文件—存放位置&#xff08;2&#xff09;动态文件-…

【用人话讲算法】leetcode无重复字符的最长子串

【用人话讲算法】leetcode无重复字符的最长子串 文章目录 【用人话讲算法】leetcode无重复字符的最长子串题目简单思路&#xff08;暴力&#xff09;优化思考怎么写代码&#xff1f;怎么到下一个&#xff1f;whilefor 思路总结while和for循环总结 题目 题目的意思是说&#xff…

一台电脑上安装多个版本的python,运行互不干扰,显示位置的一些命令,

首先需要知道一些命令&#xff1a; pip show 包名 可以使用pip show 包名的方式显示位置 pip list pip方式显示的是当前环境下的库 os.environ.get&#xff08;&#xff09; python中os模块获取环境变量的一个方法 Python os.environ.get&#xff08;&#xff09;的用法 …