Skip to content

Commit

Permalink
feat(post): 完善文章
Browse files Browse the repository at this point in the history
  • Loading branch information
李济芝 committed Aug 18, 2024
1 parent cabbeef commit 6a11d46
Show file tree
Hide file tree
Showing 37 changed files with 1,941 additions and 384 deletions.
168 changes: 166 additions & 2 deletions blog-site/content/posts/java/javakeyword/transient关键字详解.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,172 @@
---
title: "transient关键字详解"
date: 2024-08-20
draft: true
date: 2024-08-18
draft: false
tags: ["Java", "关键字","详解"]
slug: "java-keyword-transient"
---

## transient
transient关键字在Java中用于声明一个类的成员变量,它表示该变量不应被序列化。当对象序列化时,该字段不会被持久化到目标字节流中。也就是说,使用transient修饰的字段在序列化过程中将被忽略,反序列化时这些字段会被初始化为默认值,基本数据类型为0,引用类型为null。

这对于敏感信息或不需要持久化的数据非常有用。比如说用户的一些敏感信息,如密码、银行卡号等,为了安全起见,不希望在网络操作中传输或者持久化到磁盘文件中,那这些字段就可以加上transient关键字。
通过避免不必要的数据序列化尤其是一些内存较大的字段,可以减少序列化和反序列化的时间、内存和存储空间消耗,提升性能。

### 使用示例
一旦字段被transient修饰,成员变量将不再是对象持久化的一部分,该变量的值在序列化后无法访问。
transient只能用于类的成员变量,不能用于方法、局部变量或类,这使得它的应用范围相对有限。
```java
public class User implements Serializable {
private static final long serialVersionUID = 1L;

private String username;
private transient String password;

public User(String username, String password) {
this.username = username;
this.password = password;
}

@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}


public class Main {
public static void main(String[] args) {
User user = new User("JohnDoe", "password123");

// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"))) {
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
}

// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"))) {
User deserializedUser = (User) ois.readObject();
// User{username='JohnDoe', password='null'}
System.out.println(deserializedUser);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
```
被transient关键字修饰的字段不能被序列化,但是一个静态变量不管是否被transient修饰,均不能被序列化。
这是因为static字段属于类而不是某个具体的对象,序列化是对象级别的操作,它保存的是对象的实例状态,而static字段是类级别的状态,不属于任何具体对象,因此在序列化过程中被忽略。
```java
class Example implements Serializable {
private static final long serialVersionUID = 1L;

private int instanceVar;
private static int staticVar = 100; // static字段

public Example(int instanceVar) {
this.instanceVar = instanceVar;
}

@Override
public String toString() {
return "Example{" +
"instanceVar=" + instanceVar +
", staticVar=" + staticVar +
'}';
}
}

public class Main {
public static void main(String[] args) {
Example example = new Example(42);

// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("example.ser"))) {
oos.writeObject(example);
} catch (IOException e) {
e.printStackTrace();
}

// 修改 static 字段的值
Example.staticVar = 200;

// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("example.ser"))) {
Example deserializedExample = (Example) ois.readObject();
System.out.println(deserializedExample);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
```

### transient与序列化
在Java中,对象的序列化可以通过实现两种接口来实现,如果实现的是`Serializable`接口,则所有的序列化将会自动进行。
如果实现的是`Externalizable`接口,则需要在`writeExternal`方法中指定要序列化的字段,与transient关键字修饰无关。
```java
class Employee implements Externalizable {
private String name;
private transient int age; // `transient` 在 `Externalizable` 中不起作用

public Employee() {} // 无参构造函数必须存在

public Employee(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeInt(age); // 手动指定要序列化的字段
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
age = in.readInt(); // 手动指定如何反序列化
}
}
```
`Serializable`是Java标准库提供的接口,而`Externalizable``Serializable`的子接口。
使用`Externalizable`接口需要实现`readExternal``writeExternal`方法,需要手动完成序列化和反序列化的过程。
因为需要手动完成,所以`Externalizable`接口提供了更高的序列化控制能力,可以在序列化和反序列化过程中对对象进行自定义的处理,如对一些敏感信息进行加密和解密。

### transient底层原理
transient译为“临时的”,它可以阻止字段被序列化到文件中,在被反序列化后,transient字段的值被设为初始值,比如int型的初始值为0,对象型的初始值为null。
static和transient修饰的字段是不会被序列化的,在序列化底层代码中可以看到相关源代码`ObjectStreamClass`方法:
```java
private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
// 获取该类中声明的所有字段
Field[] clFields = cl.getDeclaredFields();
ArrayList<ObjectStreamField> list = new ArrayList<>();
int mask = Modifier.STATIC | Modifier.TRANSIENT;

// 遍历所有字段,将非 static 和 transient 的字段添加到 list 中
for (int i = 0; i < clFields.length; i++) {
Field field = clFields[i];
int mods = field.getModifiers();
if ((mods & mask) == 0) {
// 根据字段名、字段类型和字段是否可序列化创建一个 ObjectStreamField 对象
ObjectStreamField osf = new ObjectStreamField(field.getName(), field.getType(), !Serializable.class.isAssignableFrom(cl));
list.add(osf);
}
}

int size = list.size();
// 如果 list 为空,则返回一个空的 ObjectStreamField 数组,否则将 list 转换为 ObjectStreamField 数组并返回
return (size == 0) ? NO_FIELDS :
list.toArray(new ObjectStreamField[size]);
}
```
当一个类中的字段被标记为 transient,Java的序列化机制在序列化对象时,会忽略这些transient字段。具体来说,序列化过程中会跳过这些字段,不将其写入到对象的字节流中。
```java
int mask = Modifier.STATIC | Modifier.TRANSIENT;
```
这段代码表明,这两个修饰符标记的字段就没有被放入到序列化的字段中。
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ top: true
---

## API
API即Application Programming Interface 的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。
API即Application Programming Interface的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。
简而言之,API 就是软件系统的“接口”,它定义了其他程序如何与之交互。通过 API,开发者可以利用已有的服务或库,而不需要了解其内部实现细节。

## CI/CD
CI,Continuous Integration 的缩写,翻译过来是持续集成。就是频繁地将代码更改集成到主分支,每次集成后自动执行构建和测试,确保代码的稳定性和功能性。目的是尽早发现和解决集成问题,减少集成成本。
CI是Continuous Integration的缩写,翻译过来是持续集成。就是频繁地将代码更改集成到主分支,每次集成后自动执行构建和测试,确保代码的稳定性和功能性。目的是尽早发现和解决集成问题,减少集成成本。

CD,Continuous Delivery 的缩写,翻译过来是持续交付。在持续集成的基础上,将代码自动化地部署到生产环境之前的所有阶段。通过自动化测试和构建,确保软件可以随时交付到生产环境。目的是确保软件在任何时刻都可以发布,从而加快发布周期。
CD是Continuous Delivery的缩写,翻译过来是持续交付。在持续集成的基础上,将代码自动化地部署到生产环境之前的所有阶段。通过自动化测试和构建,确保软件可以随时交付到生产环境。目的是确保软件在任何时刻都可以发布,从而加快发布周期。

## Code Review
Code Review 翻译成中文是代码评审。Code Review 是一种通过复查代码提高代码质量的过程,通过这个机制我们可以对代码、测试过程和注释进行检查。

## CDN
即Content Delivery Network 的缩写,即内容分发网络。通过将内容缓存在终端用户附近,使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
即Content Delivery Network的缩写,即内容分发网络。通过将内容缓存在终端用户附近,使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。

CND加速主要是加速静态资源,如网站上面上传的图片、媒体,以及引入的一些JS、CSS等文件。
CDN是只对网站的某一个具体的域名加速。如果同一个网站有多个域名,则访问加入CDN的域名获得加速效果,访问未加入CDN的域名,或者直接访问IP地址,则无法获得CDN效果。
Expand All @@ -36,10 +36,18 @@ DTO通常是一个简单的Java类,包含了需要传递的数据字段,通
字段通常对应于视图层或API调用所需要的数据格式,并不会完全反映底层数据库或业务实体的结构。

## DAO
DAO全称Data Access Object译为数据访问对象,主要用于将数据访问逻辑与业务逻辑分离,从而实现代码的解耦和更好的维护性。

DAO模式的核心思想是通过创建一个数据访问对象来处理与数据库的所有交互。
这样,业务逻辑层不需要直接处理数据库的细节,如SQL查询、连接管理等,而是通过DAO来进行数据的获取、插入、更新和删除等操作。
通常,DAO模式会定义一个接口,如UserDAO,该接口定义了操作数据的方法,如getUserById、saveUser等。然后,通过一个具体的类,如UserDAOImpl来实现这些方法。

## DNS
即Domain Name System 的缩写,域名系统,是将域名解析为IP地址的系统。
DNS是Domain Name System的缩写,译为域名系统,是将域名解析为IP地址的系统。

当用户在浏览器中输入一个域名时,浏览器首先查询本地缓存中是否有该域名的IP地址。如果没有,则发起DNS查询。
DNS查询通常是递归的,即从本地DNS服务器开始,一步步向上级服务器查询,直到找到目标IP地址。
查询过程通常会经过根域名服务器、顶级域名服务器(TLD服务器)、权威域名服务器,找到IP地址后,DNS服务器将结果返回给用户的设备,然后用户的设备就可以使用该IP地址来访问对应的网站或资源。

## Entity

Expand Down Expand Up @@ -117,3 +125,5 @@ URN是一种URI,用于通过名称来唯一标识资源,但不包含资源
重构的目的是使软件更容易被理解和修改。可以在软件内部做很多修改,但必须对软件可观察的外部行为只造成很小的变化,甚至不造成变化。

## 一站式
“一站式”是一种服务理念或商业模式,指的是在一个平台或地点提供满足用户某类需求的所有相关服务或产品,确保用户可以在同一地点完成整个流程,而无需在多个不同的地方奔波。
其目的是通过集成各种服务,简化流程,提升效率,提供更便捷的用户体验。
2 changes: 1 addition & 1 deletion blog-site/public/index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@
<link>http://localhost:1313/iblog/posts/java/keepupd/java-dict/</link>
<pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/iblog/posts/java/keepupd/java-dict/</guid>
<description>API API即Application Programming Interface 的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。 简而言之,API 就是软件系统的“接口</description>
<description>API API即Application Programming Interface的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。 简而言之,API 就是</description>
</item>
<item>
<title>配置IDEA及使用技巧</title>
Expand Down
2 changes: 1 addition & 1 deletion blog-site/public/page/7/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ <h2><a href='/iblog/posts/java/keepupd/java-dict/'>编程专业术语汇总及

<div class="list">
<div class="post_content markdown">
<p>API API即Application Programming Interface 的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。 简而言之,API 就是软件系统的“接口......</p>
<p>API API即Application Programming Interface的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。 简而言之,API 就是......</p>
</div>
</div>

Expand Down
7 changes: 7 additions & 0 deletions blog-site/public/posts/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ <h1>
<div class="listing_title">2024</div>
<div class="listing">

<div class="listing_item">
<div class="listing_post">
<a href="/iblog/posts/java/javakeyword/java-keyword-transient/">transient关键字详解</a>
<div class="post_time"><span class="date">08-18</span></div>
</div>
</div>

<div class="listing_item">
<div class="listing_post">
<a href="/iblog/posts/java/javakeyword/java-keyword-strictfp/">strictfp关键字详解</a>
Expand Down
11 changes: 9 additions & 2 deletions blog-site/public/posts/index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@
<description>Recent content in Posts on 脚踏实地</description>
<generator>Hugo -- gohugo.io</generator>
<language>zh</language>
<lastBuildDate>Thu, 15 Aug 2024 00:00:00 +0000</lastBuildDate>
<lastBuildDate>Sun, 18 Aug 2024 00:00:00 +0000</lastBuildDate>
<atom:link href="http://localhost:1313/iblog/posts/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>transient关键字详解</title>
<link>http://localhost:1313/iblog/posts/java/javakeyword/java-keyword-transient/</link>
<pubDate>Sun, 18 Aug 2024 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/iblog/posts/java/javakeyword/java-keyword-transient/</guid>
<description>transient transient关键字在Java中用于声明一个类的成员变量,它表示该变量不应被序列化。当对象序列化时,该字段不会被持久化到目标字节流中。也就是说,使用tra</description>
</item>
<item>
<title>strictfp关键字详解</title>
<link>http://localhost:1313/iblog/posts/java/javakeyword/java-keyword-strictfp/</link>
Expand Down Expand Up @@ -643,7 +650,7 @@
<link>http://localhost:1313/iblog/posts/java/keepupd/java-dict/</link>
<pubDate>Mon, 13 Feb 2023 00:00:00 +0000</pubDate>
<guid>http://localhost:1313/iblog/posts/java/keepupd/java-dict/</guid>
<description>API API即Application Programming Interface 的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。 简而言之,API 就是软件系统的“接口</description>
<description>API API即Application Programming Interface的缩写,翻译过来是应用程序编程接口,它是一组定义了不同软件组件之间交互方式的规范和协议。 简而言之,API 就是</description>
</item>
<item>
<title>配置IDEA及使用技巧</title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2153,7 +2153,7 @@ <h3 id="代码-5">代码</h3>
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">IOException</span><span class="w"> </span><span class="n">ex</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="s">&#34;另存为图片失败&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">ex</span><span class="p">.</span><span class="na">printStackTrace</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">JOptionPane</span><span class="p">.</span><span class="na">showMessageDialog</span><span class="p">(</span><span class="n">panel</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;另存为图片失败,&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">ex</span><span class="p">.</span><span class="na">getMessage</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;提示&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">JOptionPane</span><span class="p">.</span><span class="n">PLAIN_MESSAGE</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">JOptionPane</span><span class="p">.</span><span class="na">showMessageDialog</span><span class="p">(</span><span class="n">panel</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;另存为图片失败,&#34;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">ex</span><span class="p">.</span><span class="na">getMessage</span><span class="p">(),</span><span class="w"> </span><span class="s">&#34;提示&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">JOptionPane</span><span class="p">.</span><span class="na">PLAIN_MESSAGE</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">});</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
Expand Down
Loading

0 comments on commit 6a11d46

Please sign in to comment.