决战圣地玛丽乔亚Day37----JDK
Posted Dva清流
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了决战圣地玛丽乔亚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。
- 通道(Channel):用于数据的读写,可以实现非阻塞IO操作。
- 缓冲区(Buffer):用于数据的存储和传输,可以提高数据传输的效率。
- 选择器(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关键字修饰的成员变量在反序列化后会被赋予默认值。
以上是关于决战圣地玛丽乔亚Day37----JDK的主要内容,如果未能解决你的问题,请参考以下文章