决战圣地玛丽乔亚Day37----JDK

时间:2023-03-21
本文章向大家介绍决战圣地玛丽乔亚Day37----JDK,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

泛型:

为什么说Java是假泛型?

 java的泛型是伪泛型。Java 的泛型仅仅在编译期有效,在运行期则会被擦除,也就是说所有的泛型参数类型在编译后都会被清除掉。

例如我们无法向List<String>的集合中add进Integer类型的对象,但是如果我们通过反射,可以对add方法invoke进Integer类型的对象。

又例如:

public class Test {

public void addList(List<String> stringList){ }

public void addList(List<Integer> intList) { }

}

在我们看来,上面的两个addList方法,使用的是不同的参数,一个是Integer的List一个是String类型的List。

但是编译器会报错:

Method addList(List) has the same erasure addList(List) as another method in type Test

编译器判断两个的参数都是List<E>.

因为经历了类型擦除的过程。

下面是关于List的类型擦除的一些情况:

List<String>、List<T>擦除后的类型为List。
List<String>[]、List<T>[] 擦除后的类型为 List[]。
List<? extends E>、List<? super E>擦除后的类型为List<E>。
List<T extends Serialzable & Cloneable>擦除后类型为 List<Serializable>。

为什么要有泛型?

Java泛型的类型安全性体现在编译期间,即在代码编译时就可以进行类型检查,从而避免了在运行时可能出现的类型转换错误

使用泛型可以使代码更加清晰地表达意图,同时也可以降低代码的重复性,提高代码的复用性。

当然,泛型也有一些限制和问题,例如无法支持基本类型的参数化、无法在运行时获取泛型类型参数的信息等。

但是,在实际开发中,这些问题并不会对使用泛型带来太大的影响,而泛型的优点远远大于它的缺点。

序列化:

为什么要序列化?

Java中的序列化是指将对象转化为字节序列的过程,可以将对象在网络中传输或者保存到本地磁盘中。

数据持久化:将对象保存到本地磁盘中,以便下次使用时直接读取

网络传输:将对象序列化后通过网络进行传输

分布式应用:在分布式系统中,不同的节点需要进行数据交换,因此需要将对象序列化为字节序列进行传输和接收

缓存:将对象序列化后保存到缓存中,以便下次使用时直接读取,例如Redis中的缓存机制

为什么要实现Serializable接口?

Serializable接口是一个标记接口,没有任何方法或属性,只是用于标记一个类是否可以被序列化。如果一个类实现了Serializable接口,就表示这个类可以被序列化,否则不能被序列化。

实现Serializable接口的类可以通过Java的序列化机制将其对象转换为字节序列,从而实现对象的持久化、网络传输等操作。

在序列化过程中,Java会将对象的状态保存为一个字节序列,包括对象的属性和方法等信息,然后将这个字节序列传输到其他地方进行反序列化,

重新生成一个相同的对象。 需要注意的是,实现Serializable接口并不是完全安全的,因为它可以被用于恶意目的。

因此,在实现Serializable接口时需要注意一些安全问题,例如使用transient关键字修饰敏感数据、禁止序列化敏感数据等。

序列化ID的含义?多个类定义同一个序列化ID有风险吗?

 序列化ID是用来标识是否是同一个类的标识。定义同一个序列化ID当然是有风险的。

如果使用JAVA内部生成的序列化ID,因为Java自动生成的序列化ID依赖于类的名称、属性、方法等信息,如果类的定义发生变化,序列化ID可能会发生改变,导致反序列化失败。

因此我们最好自己手动写一个生成序列化ID的实现,保证序列化ID的唯一性。

NIO的实现

非阻塞IO。

  1. 通道(Channel):用于数据的读写,可以实现非阻塞IO操作。
  2. 缓冲区(Buffer):用于数据的存储和传输,可以提高数据传输的效率。
  3. 选择器(Selector):用于多路复用IO操作,可以同时处理多个请求。 NIO的实现主要有以下几种:

对比BIO

BIO是阻塞型IO,它的特点是在进行IO操作时,线程会被阻塞,直到IO操作完成才会继续执行后续代码。

BIO的缺点是不能高效地处理大量并发请求,因为每个请求都需要一个独立的线程来处理,这样会导致线程数目增加、CPU资源浪费等问题。

BIO采用一请求一线程模型,NIO采用多路复用器模型,可以使用少量的线程处理大量的请求。

BIO采用同步阻塞模型,NIO采用同步非阻塞模型。 BIO的优点在于使用起来比较简单,代码易于理解和维护,适合处理并发请求较少的场景。

NIO的优点在于可以高效地处理大量并发请求,适合处理高并发的网络应用、分布式系统等场景。

IO模型有哪些:

阻塞IO模型(Blocking IO,BIO):在进行IO操作时,线程会被阻塞,直到IO操作完成才会继续执行后续代码。BIO的特点是简单、易于理解和使用,但不能高效地处理大量并发请求。

非阻塞IO模型(Non-blocking IO,NIO):在进行IO操作时,线程不会被阻塞,而是通过轮询的方式不断地检查IO操作是否完成。NIO可以高效地处理大量并发请求,适用于高并发的网络应用、分布式系统等场景。

多路复用IO模型(Multiplexing IO,MIO):通过一个线程同时监视多个IO操作,实现了多个IO操作的同步复用,可以大大提高IO操作的效率。MIO适用于同时处理多个IO操作的场景。

信号驱动IO模型(Signal-driven IO,SIO):在进行IO操作时,线程不会被阻塞,而是通过信号的方式通知IO操作已经完成。SIO适用于只需要处理少量并发请求、但需要及时处理IO操作的场景。

异步IO模型(Asynchronous IO,AIO):在进行IO操作时,线程不需要等待IO操作完成,而是通过回调函数的方式在IO操作完成后再进行处理。AIO适用于需要处理大量并发请求、但需要及时响应的场景。 不同的IO模型适用于不同的应用场景,需要根据具体的需求选择合适的IO模型。

异常管理:

编译异常(编译期异常,需要抛出处理,必须处理)

运行异常(运行期异常,需要改代码,可以不出来抛出去)

ERROR(运行时的严重问题)

对于一些关键字的理解:

final:

1.修饰的类不能被继承

2.修饰的方法不能被子类重写

3.修饰的变量不可被修改

4.修饰的方法参数不能被修改

5.可以提高性能,因为JVM在编译时会对final方法进行优化,将方法调用转为静态绑定,从而提高程序的运行效率

static

1.修饰的变量也叫类变量,所有实例共享

2.修饰的方法是静态方法,也称为类方法,不需要实例化对象即可调用,只能访问静态变量或调用其他静态方法

3.修饰的代码块是静态代码块,在类加载时只执行一次,用于对静态变量进行初始化

4.修饰的内部类是静态内部类,与普通内部类不同,静态内部类不需要依赖于外部类实例化即可进行实例化。例如:public static class MyInnerClass { ... },表示MyInnerClass是一个静态内部类,可以通过类名直接实例化,例如:MyClass.MyInnerClass myInnerClass = new MyClass.MyInnerClass()。

transient

1.修饰类的成员变量,表示这个成员变量不需要进行序列化

2.当一个对象需要被序列化时,如果对象中有某个成员变量不需要被序列化,可以使用transient关键字进行修饰,这样在序列化时,这个成员变量就会被忽略掉

 transient关键字的作用是保护敏感数据不被序列化,例如密码等敏感信息。当对象被序列化后,敏感数据被忽略,不会被保存到文件中,从而增加了数据的安全性。 需要注意的是,使用transient关键字修饰的成员变量在反序列化后会被赋予默认值。

原文地址:https://www.cnblogs.com/dwj-ngu/p/17238566.html