提交 86e54a98 编写于 作者: W wizardforcel

2020-06-23 21:44:12

上级 c7387d1f
......@@ -2,7 +2,7 @@
> 原文: [https://javabeginnerstutorial.com/python-tutorial/object-oriented-programming-in-python/](https://javabeginnerstutorial.com/python-tutorial/object-oriented-programming-in-python/)
与在 Python 中一样,在开发程序时不必将代码创建为类,因为我们可以使用也称为过程编程的函数。 但是,过程编程用于编写小型,简短和简单的程序,而面向对象的编程(OOP)程序随着程序的大小和复杂性的增长而变得越来越重要。 自从开发以来,Python 一直是面向对象的语言。
与在 Python 中一样,在开发程序时不必将代码创建为类,因为我们可以使用也称为过程编程的函数。 但是,过程编程用于编写小型,简短和简单的程序,而面向对象的编程(OOP)程序随着程序的大小和复杂性的增长而变得越来越重要。 自从开发以来,Python 一直是面向对象的语言。
因此,让我们简要介绍一下所使用的面向对象的编程概念-
......
......@@ -4,7 +4,7 @@
在这里,我们将详细了解`List`接口及其不同实现。 `java.util`包中的列表接口是`java.util.Collection`接口的子类型。
## `List`接口显着
## `List`接口
1. 它是`java.util`包的一部分。
2. 它是`java.util.Collection`接口的子类型。
......
......@@ -2,51 +2,51 @@
> 原文: [https://javabeginnerstutorial.com/core-java-tutorial/set-collection-tutorial-for-java-beginners/](https://javabeginnerstutorial.com/core-java-tutorial/set-collection-tutorial-for-java-beginners/)
`Set`是 Java 集合框架的一部分。 `Set` *java.util* 程序包中的一个接口。 它实现了 Collection 接口。
`Set`是 Java 集合框架的一部分。 `Set``java.util`程序包中的一个接口。 它实现了`Collection`接口。
# 与集有关的要点
# 与集有关的要点
* 它不包含重复的元素。
* 一些 Set 实现对 NULL 元素有限制。
* 一些`Set`实现对`NULL`元素有限制。
# 设置接口的具体实现
# `Set`接口的具体实现
* 哈希集
* 链接哈希集
* 树集
* EnumSet
* `HashSet`
* `LinkedHashSet`
* `TreeSet`
* `EnumSet`
# 设置界面中的重要方法
此接口不包含任何特殊方法。 它仅继承 Collection 接口的所有方法。
此接口不包含任何特殊方法。 它仅继承`Collection`接口的所有方法。
# 哈希集
# `HashSet`
* 此类是 Java CollectionFramework 的一部分。
* 此类实现 Set 接口。
* 此类是 Java 集合框架的一部分。
* 此类实现`Set`接口。
* 它由哈希表支持。
* 它是无序的。 (随着时间的推移,订单不可预测)
* 基本操作(如添加,删除,包含和大小)的恒定时间性能。
* 它不同步。
* Iterator 方法返回的迭代器为 FailFast
* `Iterator`方法返回的迭代器为快速失败
## 构造器
* **`HashSet(Collection<? extends E> c)`**:构造一个新集合,其中包含指定集合中的元素。
* **`HashSet(int initialCapacity, float loadFactor)`**:构造一个新的空集; 支持的 HashMap 实例具有指定的初始容量和指定的负载系数。
* **`HashSet(int initialCapacity, float loadFactor)`**:构造一个新的空集; 支持的`HashMap`实例具有指定的初始容量和指定的负载系数。
* **`HashSet(int initialCapacity)`**:构造一个新的空集。
# 链接哈希集
# `LinkedHashSet`
* 元素的顺序是可预测的。
* 它维护遍历所有条目的双链表。
* 元素的顺序将与插入顺序相同。
* 它允许 NULL 值。
* HashSet 一样,它为基本操作提供恒定的时间性能。
* 它允许`NULL`值。
*`HashSet`一样,它为基本操作提供恒定的时间性能。
* 链接列表上的迭代时间与大小成正比。
* 初始容量和负载因子决定 LinkedHashSet 的性能。
* 初始容量和负载因子决定`LinkedHashSet`的性能。
* 它不同步。
* 此类的 Iterator 方法返回的 Iterator 为 FAIL-FAST
* 此类的`Iterator`方法返回的迭代器为快速失败
## 构造器
......@@ -54,5 +54,3 @@
* **`LinkedHashSet(int initialCapacity)`**:构造一个新的,空的,具有指定初始容量和默认加载因子 0.75 的链接哈希集。
* **`LinkedHashSet()`**:构造一个新的空链接哈希集,默认初始容量为 16,负载因子为 0.75。
* **`LinkedHashSet(Collection<? extends E> c)`**:构造一个新的链接哈希集,其元素与指定的集合相同。
# 树集
\ No newline at end of file
# Java 初学者的排序集集合教程
# Java 初学者的`SortedSet`集合教程
> 原文: [https://javabeginnerstutorial.com/core-java-tutorial/sorted-set-collection-tutorial-for-java-beginners/](https://javabeginnerstutorial.com/core-java-tutorial/sorted-set-collection-tutorial-for-java-beginners/)
该接口是 Java Collection Interface 的一部分。
该接口是 Java 集合接口的一部分。
SortedSet 的重要点
`SortedSet`的重要点
* 它提供其元素的顺序。
* 元素根据创建 SortedSet 时提供的 Comparable / Comparator 进行排序。
* 元素根据创建`SortedSet`时提供的`Comparable`/`Comparator`进行排序。
* 迭代器将以升序遍历集合。
* 此接口是 SortedMap 的集合类似物。
* 插入 SortedSet 中的元素需要实现 Comparable 接口(或接受比较器接口)。
* SortedSet 的所有实现应提供 4 个构造器。
* 没有 Arg 构造器
* 具有 Comparator 单个参数的构造器。
* 具有单个参数的构造方法为 Collection
* 具有单个参数的构造器为 SortedSet
* 此接口是`SortedMap`的集合类似物。
* 插入`SortedSet`中的元素需要实现`Comparable`接口(或接受比较器接口)。
* `SortedSet`的所有实现应提供 4 个构造器。
* 没有带参构造器
* 具有单个`Comparator`参数的构造器。
* 具有单个`Collection`参数的构造器
* 具有单个`SortedSet`参数的构造器
# SortedSet 中的重要方法
# `SortedSet`中的重要方法
* **`Comparator<? super E> comparator()`**:返回用于对 Set 中的元素进行排序的比较器。
* **`subSet(E fromElement, E toElement)`**:返回此集合部分的视图,其元素范围从 fromElement(包括)到 toElement(不包括)。
* **`headSet(E toElement)`**:返回此集合中的元素严格小于 toElement 的部分的视图。
* **`tailSet(E fromElement)`**:返回此集合中其元素大于或等于 fromElement 的部分的视图
\ No newline at end of file
* **`Comparator<? super E> comparator()`**:返回用于对`Set`中的元素进行排序的比较器。
* **`subSet(E fromElement, E toElement)`**:返回此集合部分的视图,其元素范围从`fromElement`(包括)到`toElement`(不包括)。
* **`headSet(E toElement)`**:返回此集合中的元素严格小于`toElement`的部分的视图。
* **`tailSet(E fromElement)`**:返回此集合中其元素大于或等于`fromElement`的部分的视图
\ No newline at end of file
# Java 初学者排序映射收藏教程
# Java 初学者`SortedMap`集合教程
> 原文: [https://javabeginnerstutorial.com/core-java-tutorial/sorted-map-collection-tutorial-for-java-beginners/](https://javabeginnerstutorial.com/core-java-tutorial/sorted-map-collection-tutorial-for-java-beginners/)
## SortedMap 的显着
## `SortedMap`的要
* 此接口是 SortedSet 的映射类似物。
* IT 提供按键排序。
* 排序标准将是创建时提供的自然顺序或 Comparator
* 其中使用的键必须实现 Comparable 或接受指定的比较器。
* 此接口是`SortedSet`的映射类似物。
* 它按键提供顺序。
* 排序标准将是创建时提供的自然顺序或`Comparator`
* 其中使用的键必须实现`Comparable`或接受指定的比较器。
* 该图中的键必须相互可比较。
* 使用 Map 接口 equals 方法比较两个键,而在 SortedMap 中使用 compare / compareTo 方法(来自 Comparable 或 Comparator)。
* 使用`Map`接口`equals`方法比较两个键,而在`SortedMap`中使用`compare`/`compareTo`方法(来自`Comparable``Comparator`)。
* 需要由具体类实现的构造方法
* Arg 构造器
* 具有 Comparator 单个参数的构造器。
* 具有单个参数的构造器作为 Map
* 具有单个参数的构造器,如 SortedMap
* SortedMap 是 Java Collection Framework 的一部分。
*构造器
* 具有单个`Comparator`参数的构造器。
* 具有单个`Map`参数的构造器
* 具有单个`SortedMap`参数的构造器
* `SortedMap`是 Java 集合框架的一部分。
# SortedMap 界面中的重要方法
# `SortedMap`界面中的重要方法
* **`subMap(K fromKey, K toKey)`**:返回此映射部分的视图,其元素范围从 fromElement(包括)到 toElement(不包括)。
* **`headMap(K toKey)`**:返回此映射部分的视图,其元素严格小于 toElement。
* **`tailMap(K fromKey)`**:返回此图的一部分,其元素大于或等于 fromElement 的视图。
\ No newline at end of file
* **`subMap(K fromKey, K toKey)`**:返回此映射部分的视图,其元素范围从`fromElement`(包括)到`toElement`(不包括)。
* **`headMap(K toKey)`**:返回此映射部分的视图,其元素严格小于`toElement`
* **`tailMap(K fromKey)`**:返回此图的一部分,其元素大于或等于`fromElement`的视图。
\ No newline at end of file
......@@ -6,7 +6,7 @@
## 什么是序列化
Java 序列化是一个过程,其中 Object 的当前状态将保存在字节流中。 字节流是平台无关的,因此一旦在一个系统中创建了对象,便可以在其他平台上反序列化。
Java 序列化是一个过程,其中对象的当前状态将保存在字节流中。 字节流是平台无关的,因此一旦在一个系统中创建了对象,便可以在其他平台上反序列化。
## 序列化有什么用
......@@ -23,7 +23,7 @@ Java 序列化是一个过程,其中 Object 的当前状态将保存在字节
Java 已经提供了开箱即用的方式(`java.io.Serializable`接口)来序列化对象。 如果要序列化任何类,则该类需要实现给定的接口。
**注**:可序列化接口是标记接口。 因此,Serializable 接口中没有任何方法。
**注**:可序列化接口是标记接口。 因此,`Serializable`接口中没有任何方法。
## Java 类序列化代码
......@@ -118,15 +118,15 @@ Last Name of Employee: Gautam
### 项目要点
* **序列化**接口需要使对象*序列化*
* 暂时[实例变量](https://javabeginnerstutorial.com/core-java-tutorial/instance-variable-java/)并未以对象状态序列化。
* 如果 Super 类实现了 Serializable,则子类也可以自动进行 Serializable
* 如果无法对超类进行序列化,则在对子类进行反序列化时,将调用超类的默认[构造器](https://javabeginnerstutorial.com/core-java-tutorial/constructors-in-java/)。 因此,所有变量将获得默认值,引用将为 null
* 瞬态[实例变量](https://javabeginnerstutorial.com/core-java-tutorial/instance-variable-java/)并未以对象状态序列化。
* 如果超类实现了`Serializable`,则子类也可以自动进行`Serializable`
* 如果无法对超类进行序列化,则在对子类进行反序列化时,将调用超类的默认[构造器](https://javabeginnerstutorial.com/core-java-tutorial/constructors-in-java/)。 因此,所有变量将获得默认值,引用将为`null`
在下一篇文章中,我们将讨论[瞬态变量](https://javabeginnerstutorial.com/core-java-tutorial/java-serialization-concept-example-part-ii/ "Java serialization concept and Example Part II")的使用。
* **序列化**接口需要使对象*序列化*
* 暂时[实例变量](https://javabeginnerstutorial.com/core-java-tutorial/instance-variable-java/)并未以对象状态序列化。
* 如果 Super 类实现了 Serializable,则子类也可以自动进行 Serializable。
* 如果无法对超类进行序列化,则在对子类进行反序列化时,将调用超类的默认[构造器](https://javabeginnerstutorial.com/core-java-tutorial/constructors-in-java/)。 因此,所有变量将获得默认值,引用将为 null。
\ No newline at end of file
* 瞬态[实例变量](https://javabeginnerstutorial.com/core-java-tutorial/instance-variable-java/)并未以对象状态序列化。
* 如果超类实现了`Serializable`,则子类也可以自动进行`Serializable`
* 如果无法对超类进行序列化,则在对子类进行反序列化时,将调用超类的默认[构造器](https://javabeginnerstutorial.com/core-java-tutorial/constructors-in-java/)。 因此,所有变量将获得默认值,引用将为`null`
\ No newline at end of file
......@@ -6,7 +6,7 @@
在本文中,我们将使用与上一篇文章相同的代码库。
## 使用 serialVersionUID
## 使用`serialVersionUID`
您必须已经看到在源代码中使用了一个名为“`serialVersionUID`”的变量。 使用此变量有特定的原因。
......@@ -16,14 +16,14 @@
* 如果可序列化的类具有显式的`serialVersionUID`,则此字段的类型应为`long`,并且必须是静态且最终的。
* 如果没有明确定义的`serialVersionUID`字段,则序列化运行时将计算该类的默认值。 随编译器的实现而有所不同。 因此建议定义`serialVersionUID`
* 建议对`serialVersionUID`使用私有访问修饰符。
* 数组类无法声明显式的 serialVersionUID,因此它们始终具有默认的计算值,但是对于数组类,无需匹配 serialVersionUID 值。
* 如果已加载的接收器类的 serialVersionUID 与相应的发送器类之间存在差异,则将引发 `InvalidClassException`
* 数组类无法声明显式的`serialVersionUID`,因此它们始终具有默认的计算值,但是对于数组类,无需匹配`serialVersionUID`值。
* 如果已加载的接收器类的`serialVersionUID`与相应的发送器类之间存在差异,则将引发 `InvalidClassException`
## 瞬态的使用
我们可以使用 Serializable 保存对象的状态。 但是,如果我不想保存字段状态怎么办? 在这种情况下,可以像下面这样使用瞬态修改器。 序列化过程中不会保存瞬态字段状态,反序列化时会将默认值分配给同一变量。
我们可以使用`Serializable`保存对象的状态。 但是,如果我不想保存字段状态怎么办? 在这种情况下,可以像下面这样使用瞬态修改器。 序列化过程中不会保存瞬态字段状态,反序列化时会将默认值分配给同一变量。
使用瞬态变量更改 Employee 类。
使用瞬态变量更改`Employee`类。
```java
package com.jbt;
......@@ -44,7 +44,7 @@ public class Employee implements Serializable
}
```
如果您执行相同的类(SerializaitonClass & DeserializationClass),则输出将与之前的代码不同。
如果您执行相同的类(`SerializaitonClass`&`DeserializationClass`),则输出将与之前的代码不同。
```java
Deserializing Employee...
......@@ -52,13 +52,13 @@ First Name of Employee: Vivekanand
Last Name of Employee: null
```
如您所见,姓氏为 null,因为在序列化过程中未保存该变量的状态。
如您所见,姓氏为`null`,因为在序列化过程中未保存该变量的状态。
## 类层次结构和可序列化
在这里,我将讨论 Serializable 接口对类层次结构的影响。 如果一个类实现了 Serializable 接口,则可以保存该类的状态。 但是,如果同一类扩展了另一个未实现可序列化接口的类,则不会保存超类的状态。
在这里,我将讨论`Serializable`接口对类层次结构的影响。 如果一个类实现了`Serializable`接口,则可以保存该类的状态。 但是,如果同一类扩展了另一个未实现可序列化接口的类,则不会保存超类的状态。
为了了解区别,我们将更新原始的 Employee 类。 现在,该类将扩展另一个类 *superEmployee* 。 该超类将不会实现 Serializable 接口。
为了了解区别,我们将更新原始的`Employee`类。 现在,该类将扩展另一个类`superEmployee`。 该超类将不会实现`Serializable`接口。
```java
package com.jbt;
......@@ -75,7 +75,7 @@ class superEmployee {
}
```
如果您一个接一个地执行“ SerializaitonClass”和“ DeserializationClass”,那么输出将如下所示
如果您一个接一个地执行“`SerializaitonClass`”和“`DeserializationClass`”,那么输出将如下所示
```java
Deserializing Employee...
......@@ -85,9 +85,4 @@ Last Name of Employee: null
## 瞬态与静态变量
我已经写了一篇完整的文章。 请在此处访问[](https://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/ "Transient vs Static variable java")
## 自定义序列化过程
< TO_DO >
我已经写了一篇完整的文章。 [请在此处访问](https://javabeginnerstutorial.com/core-java-tutorial/transient-vs-static-variable-java/ "Transient vs Static variable java")
......@@ -10,7 +10,7 @@
## 瞬态变量
如果您不想保存变量的状态,请在序列化时使用。 您必须将该变量标记为 Transient。 环境将知道应忽略此变量,并且不会保存相同的值。
如果您不想保存变量的状态,请在序列化时使用。 您必须将该变量标记为`Transient`。 环境将知道应忽略此变量,并且不会保存相同的值。
> 即使概念是完全不同的,并且不进行储蓄的原因也不同,人们仍然对两者的存在感到困惑。 与这两种情况一样,变量值将不会保存。
......@@ -106,13 +106,13 @@ public class DeserializationClass {
}
```
首先执行“ SerializaitonClass”,您将获得以下输出。
首先执行“`SerializaitonClass`”,您将获得以下输出。
```java
Serialized data is saved in ./employee.txt file
```
其次,执行“ DeserializationClass”,您将获得以下输出
其次,执行“`DeserializationClass`”,您将获得以下输出
```java
Deserializing Employee...
......@@ -162,18 +162,20 @@ Company CEO: Jayshree
Company Address: null
```
非常仔细地查看输出。 此处已保存 companyName,companyCEO 的值,但未保存地址的值。 另外,检查这些变量的保存值。
非常仔细地查看输出。 此处已保存`companyName``companyCEO`的值,但未保存地址的值。 另外,检查这些变量的保存值。
公司名称:TATA
公司首席执行官:Jayshree
```java
Company Name: TATA
Company CEO: Jayshree
```
在这两种情况下,此处存储的 case 值均来自 class(Employee class),而不是 Object(emp object)。 此外,即使是临时变量,也会保存 companyCEO 变量值。 因为 static 修饰符会更改此变量的行为。
在这两种情况下,此处存储的`case`值均来自类(`Employee`类),而不是对象(`emp`对象)。 此外,即使是临时变量,也会保存`companyCEO`变量值。 因为`static`修饰符会更改此变量的行为。
## 重点
1. 静态变量无法序列化。
2. 在反序列化时,如果在基类的初始化过程中提供了相同的值,则可用于静态变量。
* 这并不意味着静态变量将被序列化。 这仅意味着静态变量将使用相同的值初始化,并在加载类时分配(在这种情况下为 TATA)。 如果之前未加载类(新 JVM)。 请注意示例代码。
* 这并不意味着静态变量将被序列化。 这仅意味着静态变量将使用相同的值初始化,并在加载类时分配(在这种情况下为`TATA`)。 如果之前未加载类(新 JVM)。 请注意示例代码。
* 如果类已经在 JVM 中加载并且静态变量值已更改,那么将显示更改后的值。
3. 如果将变量定义为“静态”和“瞬态”,则静态修饰符将控制变量的行为,而不是瞬态。
* 静态和瞬态是不同的。 在某些情况下,它们的行为看起来相同,但并非总是如此。 如果在加载类时为变量分配了一个值,则在反序列化类时该值将分配给静态变量,而不是瞬时的。 因此,如果您同时使用这两个修饰符和变量,那么从某种意义上来说,我要说的是静态将优先于瞬态。
......@@ -181,7 +183,7 @@ Company Address: null
## 最终修饰符对序列化的影响
要查看 Final 修饰符的效果,我再次更改 Employee 类的代码。
要查看`Final`修饰符的效果,我再次更改`Employee`类的代码。
`Employee.java`
......@@ -223,7 +225,7 @@ Company Address: DEL
## 界面和最终
我看到了一种情况,您可以序列化未序列化的 Interface 内部的变量。
我看到了一种情况,您可以序列化未序列化的接口内部的变量。
`Employee.java`
......
# serialVersionUID 的用途是什么
# `serialVersionUID`的用途是什么
> 原文: [https://javabeginnerstutorial.com/core-java-tutorial/use-serialversionuid/](https://javabeginnerstutorial.com/core-java-tutorial/use-serialversionuid/)
在这里,我将讨论在可序列化类中使用的变量 serialVersionUID 的重要性。
在这里,我将讨论在可序列化类中使用的变量`serialVersionUID`的重要性。
下面是一个使您了解变量的确切用法的示例。
## 示例程
## 示例程
Employee.java
`Employee.java`
```java
package com.jbt;
......@@ -23,7 +23,7 @@ public class Employee implements Serializable
}
```
SerializaitonClass.java(此类将用于序列化)
`SerializaitonClass.java`(此类将用于序列化)
```java
package com.jbt;
......@@ -53,7 +53,7 @@ public class SerializaitonClass {
}
```
DeserializationClass.java(此类将用于反序列化)
`DeserializationClass.java`(此类将用于反序列化)
```java
package com.jbt;
......@@ -84,7 +84,7 @@ public class DeserializationClass {
}
```
现在执行“ SerializationClass.java”,然后执行“ DeserializationClass.java”。 它将首先创建一个具有 Employee 对象状态的文件,然后在反序列化时从同一文件创建一个对象。 输出将如下所示。
现在执行“`SerializationClass.java`”,然后执行“`DeserializationClass.java`”。 它将首先创建一个具有`Employee`对象状态的文件,然后在反序列化时从同一文件创建一个对象。 输出将如下所示。
```java
Serialized data is saved in ./employee.txt file
......@@ -96,9 +96,9 @@ First Name of Employee: Vivekanand
Last Name of Employee: Gautam
```
现在让我们尝试从 Employee.java 文件中删除“ serialVersionUID”变量,然后再次运行“ SerializationClass.java”文件。 它将再次创建带有对象状态的“ employee.txt”文件。 现在让我们在 Employee 类中假设字符串地址中添加一个新变量。
现在让我们尝试从`Employee.java`文件中删除“`serialVersionUID`”变量,然后再次运行“`SerializationClass.java`”文件。 它将再次创建带有对象状态的“`employee.txt`”文件。 现在让我们在`Employee`类中假设字符串地址中添加一个新变量。
Employee.java
`Employee.java`
```java
package com.jbt;
......@@ -115,7 +115,7 @@ public class Employee implements Serializable
}
```
现在运行“ DeserializationClass.java”并查看输出。
现在运行“`DeserializationClass.java`”并查看输出。
```java
java.io.InvalidClassException: com.jbt.Employee; local class incompatible: stream classdesc serialVersionUID = 5462223600, local class serialVersionUID = -3607530122250644586
......@@ -128,7 +128,7 @@ java.io.InvalidClassException: com.jbt.Employee; local class incompatible: strea
at com.jbt.DeserializationClass.main(DeserializationClass.java:11)
```
它将引发不兼容的异常。 因为给定的类 Employee.java 在序列化和反序列化过程之间进行了更改。 因此,系统无法识别它仍然是同一类。 为了使我们的系统了解到它是同一类,您必须在一个类中使用`serialVersionUID`变量。
它将引发不兼容的异常。 因为给定的类`Employee.java`在序列化和反序列化过程之间进行了更改。 因此,系统无法识别它仍然是同一类。 为了使我们的系统了解到它是同一类,您必须在一个类中使用`serialVersionUID`变量。
您可以尝试执行上述步骤,但保持`serialVersionUID`不变,并查看输出。 反序列化过程将正常进行。
......@@ -139,11 +139,11 @@ java.io.InvalidClassException: com.jbt.Employee; local class incompatible: strea
* 如果没有明确定义的`serialVersionUID`字段,则序列化运行时将计算该类的默认值。 该值可以根据编译器的实现而变化。 因此,建议定义`serialVersionUID`
* 建议对`serialVersionUID`使用私有访问修饰符。
* 不同的类可以具有相同的`serialVersionUID`
* 数组类无法声明显式的 serialVersionUID,因此它们始终具有默认的计算值,但是对于数组类,无需匹配 serialVersionUID 值。
* 如果已加载的接收器类的 serialVersionUID 与相应的发送器类之间存在差异,则将引发`InvalidClassException`
* 数组类无法声明显式的`serialVersionUID`,因此它们始终具有默认的计算值,但是对于数组类,无需匹配`serialVersionUID`值。
* 如果已加载的接收器类的`serialVersionUID`与相应的发送器类之间存在差异,则将引发`InvalidClassException`
* 如果要禁止序列化同一类旧版本的新类,则应对同一类的不同版本使用不同的`serialVersionUID`
## @SuppressWarnings(“序列”)
## `@SuppressWarnings("serial")`
如果您没有在应该序列化的类中提供 serialVersionId,则编译器将给出有关该序列的警告消息。 如果要覆盖此警告,则可以使用给定的注释。 使用后,编译器将不再报错缺少的 serialVersionUID
如果您没有在应该序列化的类中提供`serialVersionId`,则编译器将给出有关该序列的警告消息。 如果要覆盖此警告,则可以使用给定的注释。 使用后,编译器将不再报错缺少的`serialVersionUID`
......@@ -30,7 +30,7 @@ public static final String FRIDAY = "Friday";
}
```
现在,Schedule 类将如下所示:
现在,`Schedule`类将如下所示:
```java
public class Schedule {
......@@ -41,9 +41,9 @@ private String workday;
}
```
我想您已经看到了这种方法的缺点:即使 Workdays 类中未定义工作日,也可以轻松地将工作日设置为“星期六”或“星期日”。 此解决方案不是价值安全的。 这不是我们想要实现的。
我想您已经看到了这种方法的缺点:即使`Workdays`类中未定义工作日,也可以轻松地将工作日设置为“星期六”或“星期日”。 此解决方案不是价值安全的。 这不是我们想要实现的。
为了解决这个问题,我们将 Workdays 类转换为一个枚举:
为了解决这个问题,我们将`Workdays`类转换为一个枚举:
```java
public enum Workday {
......@@ -51,7 +51,7 @@ MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
}
```
所需的打字次数更少,现在该解决方案是价值安全的。 我们只需要调整 Schredule 类:
所需的打字次数更少,现在该解决方案是价值安全的。 我们只需要调整`Schredule`类:
```java
public class Schedule {
......@@ -69,7 +69,7 @@ public void setWorkday(Workday workday) {
## 有条件的枚举
枚举非常适合条件表达式(如果是语句或切换块)。 关于枚举的好处是它们是常量值,因此您可以将它们与==运算符进行比较,该运算符比使用 equals()更优雅-并且避免了可能的 NullPointerExceptions。 顺便说一句:如果您查看 Enum 类 equals()的实现,您将看到以下内容:
枚举非常适合条件表达式(如果是语句或切换块)。 关于枚举的好处是它们是常量值,因此您可以将它们与`==`运算符进行比较,该运算符比使用`equals()`更优雅-并且避免了可能的`NullPointerExceptions`。 顺便说一句:如果您查看`Enum``equals()`的实现,您将看到以下内容:
```java
public final boolean equals(Object other) {
......@@ -77,7 +77,7 @@ public final boolean equals(Object other) {
}
```
因此,请自由使用==,因为这是 equals()的默认实现。
因此,请自由使用`==`,因为这是`equals()`的默认实现。
让我们看一下如何使用它们的示例:
......@@ -107,7 +107,7 @@ default:
## 迭代枚举
迭代枚举非常简单。 枚举类定义了一个称为 values()的方法,该方法返回给定枚举的值。 最好是看一个例子:
迭代枚举非常简单。 枚举类定义了一个称为`values()`的方法,该方法返回给定枚举的值。 最好是看一个例子:
```java
for(Workday w : Workday.values()) {
......@@ -125,11 +125,11 @@ THURSDAY
FRIDAY
```
如您所见,values()的顺序与枚举本身中定义的顺序相同。 因此,Java 不会进行任何魔术排序。
如您所见,`values()`的顺序与枚举本身中定义的顺序相同。 因此,Java 不会进行任何魔术排序。
## 枚举字段
有时,您只想将枚举打印到控制台(或以某种 UI 形式显示)。 在上面的示例(工作日)中,您可以简单地使用枚举的名称,尽管有时“ TUESDAY”似乎很喊,而“ Tuesday”更可取。 在这种情况下,您可以添加和使用 Enum 对象的自定义字段:
有时,您只想将枚举打印到控制台(或以某种 UI 形式显示)。 在上面的示例(工作日)中,您可以简单地使用枚举的名称,尽管有时“`TUESDAY`”似乎很喊,而“`Tuesday`”更可取。 在这种情况下,您可以添加和使用`Enum`对象的自定义字段:
```java
public enum Workday {
......@@ -155,9 +155,9 @@ private Workday(String representation) {
枚举字段很好,但是如何访问该字段? 我告诉过您,新的表示形式是表示该枚举的值,但是当前我们无法在枚举本身之外访问该属性。
除此之外,还有一个基本方法可用于所有枚举:name()以字符串形式返回当前值的名称。 这意味着在基本情况下,您可以使用此方法显示枚举的值(例如,在 UI 或日志条目中)。 **当然**也存在 toString()函数,但是有时开发人员会覆盖它,以使其对程序员更友好(或用户友好?)显示。 作为最佳实践,如果要显示枚举的名称,建议您使用 name()方法而不是 toString()
除此之外,还有一个基本方法可用于所有枚举:`name()`以字符串形式返回当前值的名称。 这意味着在基本情况下,您可以使用此方法显示枚举的值(例如,在 UI 或日志条目中)。 **当然**也存在`toString()`函数,但是有时开发人员会覆盖它,以使其对程序员更友好(或用户友好?)显示。 作为最佳实践,如果要显示枚举的名称,建议您使用`name()`方法而不是`toString()`
要从上面更改表示示例(当我们遍历 values()时),只需编写一个函数,该函数将返回新的变量表示并在迭代中使用它:
要从上面更改表示示例(当我们遍历`values()`时),只需编写一个函数,该函数将返回新的变量表示并在迭代中使用它:
```java
public enum Workday {
......@@ -197,13 +197,13 @@ Thursday
Friday
```
但这不是唯一可以实现枚举方法的用法。 在下一节中,我们将看到如何将 Enum 值映射到 String 并返回。
但这不是唯一可以实现枚举方法的用法。 在下一节中,我们将看到如何将`Enum`值映射到`String`并返回。
## 实现接口
关于枚举鲜为人知的一件事是它们可以实现接口。 这意味着,如果您需要不同枚举所需要的通用功能,则可以使用一个接口定义它,而枚举必须在该接口中实现方法。
一种这样的用例是使用 JPA 将枚举值存储在数据库中-尽管不是按名称或顺序(可通过@Enumeration 和 EnumType 获得),而是通过短代码。
一种这样的用例是使用 JPA 将枚举值存储在数据库中-尽管不是按名称或顺序(可通过`@Enumeration``EnumType`获得),而是通过短代码。
在这种情况下,您可以创建一个接口,其中包含将枚举转换为数据库表示形式并将枚举转换回的方法。
......@@ -223,7 +223,7 @@ public interface DatabaseEnum<T extends Enum<T>> {
}
```
该接口使用泛型(由 T 类型表示),并在 Strings 和枚举类型之间进行转换。
该接口使用泛型(由`T`类型表示),并在`String`和枚举类型之间进行转换。
要实现此界面,请扩展“工作日”示例:
......@@ -266,7 +266,7 @@ public Workday fromDatabase(String representation) {
有时,您最终得到一个采用布尔表达式的方法(或者您仅获得一个告诉您使用布尔值的项目说明,但感觉很痒)。 在这种情况下,可以随意引入一个新的枚举并使用正确的值而不是布尔值。
例如,一旦我有了一个规范,告诉我必须创建一个带有一些参数的方法和一个布尔值,称为“ rightHandSide”。 实际上,“ rightHandSide”的默认值为 false。 首先,我按照规范中的说明实现了该方法,但是这对我来说并不舒服,我认为这是摆脱这种冷酷感觉的另一种方法:
例如,一旦我有了一个规范,告诉我必须创建一个带有一些参数的方法和一个布尔值,称为“`rightHandSide`”。 实际上,“`rightHandSide`”的默认值为`false`。 首先,我按照规范中的说明实现了该方法,但是这对我来说并不舒服,我认为这是摆脱这种冷酷感觉的另一种方法:
```java
public void someMethod(String someParameter, boolean rightHandSide) {
......@@ -276,9 +276,9 @@ if(!rightHandSide) {
}
```
好吧,这似乎并不坏,但是如何扩展功能呢? 如果一方不重要怎么办? 在这种情况下,可以使用其他布尔参数扩展该方法,但从长远来看,它不会成功。 而且因为“ rightHandSide”的默认值为 false,所以我需要创建一个未提供参数的调用,并且使用 false 调用默认方法。
好吧,这似乎并不坏,但是如何扩展功能呢? 如果一方不重要怎么办? 在这种情况下,可以使用其他布尔参数扩展该方法,但从长远来看,它不会成功。 而且因为“`rightHandSide`”的默认值为`false`,所以我需要创建一个未提供参数的调用,并且使用`false`调用默认方法。
因此,我引入了一个名为 Side 的新枚举,并替换了布尔参数:
因此,我引入了一个名为`Side`的新枚举,并替换了布尔参数:
```java
public enum Side {
......@@ -297,5 +297,5 @@ if(side == Side.RIGHT_HAND) {
## 结论
如您所见,Enums 非常适合替换常量-有时也可以使用布尔方法参数。
如您所见,枚举非常适合替换常量-有时也可以使用布尔方法参数。
......@@ -4,10 +4,10 @@
可以以两种方式使用线程术语
* *java.lang.Thread* 的实例
*`java.lang.Thread`的实例
* 执行线程
线程的*实例是一个对象,与 Java 中的其他任何对象一样,它包含在堆上生存和死亡的变量和方法。 但是*执行线程*是一个单独的进程,具有其**调用** 。 即使您没有在程序中创建任何线程,一个线程也将在其中运行,然后 *main()*方法将启动该线程。*
线程的*实例*是一个对象,与 Java 中的其他任何对象一样,它包含在堆上生存和死亡的变量和方法。 但是*执行线程*是一个单独的进程,具有其*栈*调用。 即使您没有在程序中创建任何线程,一个线程也将在其中运行,然后`main()`方法将启动该线程。
**注意**:如果是线程,大多数事情都是不可预测的。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册