【Java基础】吐血整理-Java基础合集

文章目录

java数据类型概述

在这里插入图片描述
1、整数类型
byte:8 位,用于表示最小数据单位,如文件中数据,-128~127
short:16 位,很少用,-32768 ~ 32767
int:32 位、最常用,-231-1~231 (21 亿)
long:64 位、次常用 -263-1~263

2、浮点数类型
float:单精度类型,32 位,后缀 F 或 f,1 位符号位,8 位指数,23 位有效尾数。

double:64 位,最常用,后缀 D 或 d,1 位符号位,11 位指数,52 位有效尾数。

java浮点型默认为double型,所以要声明一个变量为float型时,需要在数字后面加F或者f:
3、字符类型
char:16位,java字符使用Unicode编码
4、布尔类型
boolean:true 真 和 false 假
总结
8位:Byte(字节型)
16位:short(短整型)、char(字符型)
32位:int(整型)、float(单精度型/浮点型)
64位:long(长整型)、double(双精度型)

java语言的特点

① 平台无关性,摆脱硬件束缚,“一次编写,到处运行”。

② 相对安全的内存管理和访问机制,避免大部分内存泄漏和指针越界。

③ 热点代码检测和运行时编译及优化,使程序随运行时间增长获得更高性能。

④ 完善的应用程序接口,支持第三方类库。

Java 如何实现平台无关?

所有.java 源文件经过编译形成一个字节码文件,而后在计算机上执行,但是解释程序的计算机不是一台真正意义上的计算 机,而是一台由软件和硬件模拟出来的计算机——Java 虚拟机。Java 中的所有程序都是在 JVM 上运行的。JVM 读取并处理经 过编译的与平台无关的字节码文件。Java 解释器负责将 Java 虚拟机的代码在特定的平台上运行。

JDK 和 JRE 的区别?

JDK: Java Development Kit,开发工具包。提供了编译运行 Java 程序的各种工具,包括编译器、JRE 及常用类库,是 JAVA 核心。

JRE: Java Runtime Environment,运行时环境,运行 Java 程序的必要环境,包括 JVM、核心类库、核心配置工具。

return语句和System.exit()方法

return 语句用来从当前方法中退出,返回到调用该方法的语句处,并从紧跟该语句的下一条语句继续执行。如果在 main() 方法中执行 return 语句,则使程序执行返回到 Java 运行系统,因为 Java 运行系统调用了 main()方法。
要想从程序的任意地方直接一步到位地退出程序,而不是返回到调用该方法的语句处,可以使用 System.exit(0)方法

Java 按值调用还是引用调用?

按值调用指方法接收调用者提供的值,按引用调用指方法接收调用者提供的变量地址。

Java 总是按值调用,方法得到的是所有参数值的副本,传递对象时实际上方法接收的是对象引用的副本。方法不能修改基本数据类型的参数,如果传递了一个 int 值 ,改变值不会影响实参,因为改变的是值的一个副本。

可以改变对象参数的状态,但不能让对象参数引用一个新的对象。如果传递了一个 int 数组,改变数组的内容会影响实参,而改变这个参数的引用并不会让实参引用新的数组对象。

object类中有哪些常用的方法

图片说明

==与equals()的区别

前者的作用是判断两个对象的地址是不是相等,即两个对象是不是同一个对象(基本类型比较的是值,引用数据类型比较的是地址)

equals也是判断两个对象是不是相等,但是分为两种情况

情况一:类没有覆盖equals方法,则通过equals比较该类的两个对象的时候,等价于通过“==”比较这两个对象

情况二:类覆盖了equals方法,覆盖equals方法来判断两个对象的内容相等,若他们的内容相等,则返回true

为什么重写equals方法就必须重写hashcode方法

当不重写equals方法,判断两个对象是否相等,等同于利用==判断。当重写equals方法时,判断两个对象是否相等则必须调用equals方法返回结果。考虑不重写hashcode时,虽然属性值完全相同的对象得到了相等的结果,但是当把这两个对象加入到hashset或者hashmap中则会产生异常。就结果而言,两个内容意义上相等的不同对象加入hashset,容量应该为1,但是hashset取使用hashcode判断对象是否已存在或相等所以造成了歧义,最差的结果导致hashset的不正常运行。所以重写equals方法必须重写hashcode方法

clone方法

clone方法是创建并且返回一个对象的复制之后的结果。clone方法首先会判断对象是否实现了cloneable接口,若无则抛出clonenotsupportedException异常,最后会调用internalclone

深拷贝和浅拷贝的区别

首先,深拷贝和浅拷贝是只针对 Object 和 Array 这样的引用数据类型。
那先来看看浅拷贝和深拷贝的概念。 在 Java 中,除了基本数据类型(元类型)之外,还存在类的实例对象 这个引用数据类型。而一般使用 =号做赋值操作 的时候,对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用 传递过去,他们实际上还是指向的同一个对象。

浅拷贝

如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有 真实的创建一个新的对象
在这里插入图片描述

深拷贝

在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量
在这里插入图片描述

数组的复制方法

1.for循环

2.Arrays.copyOf本质上调用System.arracopy.之所以时间差距比较大,是因为很大一部分开销花在了Math.min函数上。所以相比之下,System.arraycopy效率更高一些

3.clone比较特殊,对于对象而言,它是深拷贝,对于数组而言,它是浅拷贝

4.System.arraycopy(),对于基本数据类型来说 System.arraycopy() 方法是深拷贝;对于引用数据类型来说 System.arraycopy() 方法是浅拷贝。System.arraycopy线程不安全!!!

java基本数据类型

byte 1字节 -128-127

short 2字节 -215-215-1

int 4字节 -231-231-1

long 8字节 -2^63-2_63-1

float 4字节

double 8字节

boolean 比较特殊,当作为单变量与int相等,当作为数组占1字节

char 2字节

包装类常见的误区
public void testEquals() {
        int int1 = 12;
        int int2 = 12;
        Integer integer1 = new Integer(12);
        Integer integer2 = new Integer(12);
        Integer integer3 = new Integer(127);
        Integer a1 = 127;
        Integer a2 = 127;
        Integer a = 128;
        Integer b = 128;
        System.out.println("int1 == int2 -> " + (int1 == int2));    // true       
        System.out.println("int1 == integer1 -> " + (int1 == integer1));    // true       
        System.out.println("integer1 == integer2 -> " + (integer1 == integer2)); // false
        System.out.println("integer3 == a1 -> " + (integer3 == a1));  // false
        System.out.println("a1 == a2 -> " + (a1 == a2));       // true       
        System.out.println("a == b -> " + (a == b));        // false                           
    }
  • 1.略
  • 2.Integer是int的封装类,当Integer与int进行==比较时,Integer就会拆箱成一个int类型,所以还是相当于两个int类型进行比较
  • 3.两个都是对象类型,而且不会进行拆箱比较
  • 4.integer3是一个对象类型,而a1是一个常量它们存放内存的位置不一样,所以也不等
  • 5.128不在缓存范围内,所以会new出两个不同的对象
包装类中的缓存

包装类存在缓存池设计,当使用Integer.valueOf(123)时,会尝试从缓存池中取对象(如果存在的话),多次调用会取得同一个对象的引用;而new Integer(123)则会新建一个对象,下面是常见的比较:

Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x == y);    // false
Integer z = Integer.valueOf(123);
Integer k = Integer.valueOf(123);
System.out.println(z == k);   // true
String类

不可变性:在jdk8中,string类使用char[]数组保存值。这个char数组使用final修饰符修饰,意味着一旦确定就引用即不可修改,此外string类没有提供数组修改值得方法。此外,string类只用final修饰,表明其不可继承

string不可变性带来的好处

可作为hash的key,较少计算量

字符串缓存池

具有安全性

天生的线程安全性

String,StringBulider,StringBuffer的异同

可变性:string使用私有常量char数组,因此不可变,其他二者均使用普通的char数组

线程安全性:string由于不可变天生线程安全,stringBuffer使用synchronized关键字修饰,线程安全,stringbuilder线程不安全

性能:stringBuilder>stringBuffer>string

是否可继承:三者均不可继承

substring方法:string和stringBuffer有该方法,stringbuilder中没有

equals,valueof方法:stringbuilder和stringBuffer均没有

字符串拼接的方式有哪些?

直接用 + ,底层用 StringBuilder 实现。只适用小数量,如果在循环中使用 + 拼接,相当于不断创建新的 StringBuilder 对象再转换成 String 对象,效率极差。

② 使用 String 的 concat 方法,该方法中使用 Arrays.copyOf 创建一个新的字符数组 buf 并将当前字符串 value 数组的值拷贝到 buf 中,buf 长度 = 当前字符串长度 + 拼接字符串长度。之后调用 getChars 方法使用 System.arraycopy 将拼接字符串的值也拷贝到 buf 数组,最后用 buf 作为构造参数 new 一个新的 String 对象返回。效率稍高于直接使用 +。

③ 使用 StringBuilder 或 StringBuffer,两者的 append 方法都继承自 AbstractStringBuilder,该方法首先使用 Arrays.copyOf 确定新的字符数组容量,再调用 getChars 方法使用 System.arraycopy 将新的值追加到数组中。StringBuilder 是 JDK5 引入的,效率高但线程不安全。StringBuffer 使用 synchronized 保证线程安全。

String a = “a” + new String(“b”) 创建了几个对象?

常量和常量拼接仍是常量,结果在常量池,只要有变量参与拼接结果就是变量,存在堆。

使用字面量时只创建一个常量池中的常量,使用 new 时如果常量池中没有该值就会在常量池中新创建,再在堆中创建一个对象引用常量池中常量。因此 String a = “a” + new String(“b”) 会创建四个对象,常量池中的 a 和 b,堆中的 b 和堆中的 ab。

static关键字
  • static修饰成员变量
    存储位置不同:
    静态成员变量:位于方法区,无论多少个对象该变量在内存中都只有一份
    非静态成员变量:位于堆空间,每new一个对象创建一份,因此有多少个对象该变量在内存中就有多少份
    静态变量和类有关,与对象无关,那么count前没有隐含的this引用
  • static修饰方法
    1)由于在调用静态方法时,并不会将对象的引用传递过去,因此在静态方法中不能访问对象的非静态成员变量。静态成 员方 法访问方式:“类名.静态方法”
    2)由于静态成员方法通常以“类名.静态方法”的形式访问,如果可以访问“非静态成员变量”,那么编译器也就无法确 定: 访问的“非静态成员变量”是属于哪个对象,以及在内存中的位置,甚至根本没有对象,为避免这种情况的出现,编 译器 一定不会允许“静态成员方法”访问“非静态成员变量”
  • static修饰内部类
    静态内部类不含有外部类对象的this引用
父子类的初始化顺序
  • 父类(静态变量、静态语句块)
  • 子类(静态变量、静态语句块)
  • 父类(实例变量、普通语句块)
  • 父类(构造函数)
  • 子类(实例变量、普通语句块)
  • 子类(构造函数)
final关键字
  • 作用于基本类型变量,final 使数值不变
  • 作用于引用类型变量,final 使引用不变,也就不能引用其它对象,但是被引用的对象本身是可以修改的例如数组
  • 作用于方法,final 使得该方法不能被重写。被 final 修饰的方法运行速度快于非 final 方法,因为在编译时已经被静态绑定,而无需运行时动态绑定。private 方法则被隐式地指定为 final
  • 作用于类,final 使得该类无法被继承,例如 String,Integer
  • final 与 abstract具有反相关关系

使用final关键字的好处:

  • final 关键字提高了性能,JVM 和 Java 应用都会缓存 final 变量
  • final 变量可以安全地在多线程环境下运行,无需同步开销
  • JVM 会对 final 方法、变量、类进行优化
instanceof

instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例

super

可以使用 super() 函数访问父类的构造函数,从而委托父类进行一些初始化工作;可以使用 super.变量名 或 super.函数名 访问父类的变量或调用函数

面向对象的三大特性

(1)封装(信息隐藏):指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,
数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。(保护数据)
(2)继承(避免重复造轮子):继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,相同的行为。
(3)多态:同一个行为具有不同的表现形式或形态的能力。

重写和重载的区别

重写存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。

重载存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。应该注意的是,返回值不同,其它都相同不算是重载。

构造器可以重写吗

父类的构造器和私有属性不能被继承,所以无法重写,但是构造器其本身可以进行重载,即一个类里有多个构造函数的情况

接口和抽象类的区别
  • 是否可多继承:抽象类不可多继承;接口可以
  • 是否有构造器:抽象类可以由构造器;接口不可以
  • 是否可用静态代码块和静态方法:抽象类可以;接口不可以
  • 实现方式:extends;implements
  • 接口是对动作的抽象;抽象类是对根源抽象
接口和抽象类在不同版本的变化
  • 抽象类在1.8以前,其方法的默认访问权限为protected;1.8后改为default
  • 接口在1.8以前,方法必须是public;1.8时可以使用default;1.9时可以是private
接口和类的区别
为什么在父类要定义一个没有参数的空构造函数

Java 程序在执行子类的构造方法之前,如果没有用 super() 来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

静态类和单例的区别
  • 单例可以继承类,实现接口,而静态类不能(可以集成类,但不能集成实例成员)
  • 单例可以被延迟初始化,静态类一般在第一次加载是初始化
  • 单例类可以被集成,他的方法可以被覆写
  • 单例类可以被用于多态而无需强迫用户只假定唯一的实例
  • (静态方法)静态方法中产生的对象,会随着静态方法执行完毕而释放掉,而且执行类中的静态方法时,不会实例化静态方法所在的类。如果是用singleton,产生的那一个唯一的实例,会一直在内存中,不会被GC清除的(原因是静态的属性变量不会被GC清除),除非整个JVM退出
什么是异常

如果某个方法无法按照正常的途径完成任务,则需要提供另外一种途径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法立即退出不返回任何值。此外,调用这个方法的其他代码也无法继续执行,异常处理机制将代码执行交给异常处理器。Throwable 是所有异常或错误的超类,其子类有 Error 和 Exception,Exception 的子类有 RuntimeException 和 IOException 。

常见的五个运行时异常
  • NullPointerException(空指针)
  • ArithmeticException(运算)
  • ClassCastException(类转换异常)
  • ArrayIndexOutOfBoundsException(数组越界)
  • StringIndexOutOfBoundsException(字符串下标越界)
常见的五个编译时异常
  • FileNotFoundException
  • ClassNotFoundException
  • SQLException
  • NoSuchFieldException
  • NoSuchMethodException
Exception和Error的区别
  • Error是指Java运行时系统的内部错误和资源耗尽错误。应用程序不会抛出该类对象
  • Exception分为两种,分别是RuntimeException(非受检异常)和CheckedException(受检异常)。其中 RuntimeException 是 JVM 在正常运行期间抛出的异常的超类,表明程序员出错;CheckedException 一般发生在编译期,Java 编译器会强制程序去捕获此类异常,并将这段可能出现异常的程序进行 try-catch
throw和throws的区别
  • throws 用于函数外,后面紧跟异常类,可以有多个异常类;throw 用在函数内,只能抛出一种异常类
  • throws 用于声明可能发生的异常,且该异常不一定发生;throw 则是抛出异常,一旦执行则必然发生异常
  • 二者遇到异常都仅仅抛出,而不是进行处理,真正的处理由函数的上层调用处理
简述你对泛型的理解

泛型本质是参数化类型,解决不确定具体类型的问题。泛型在定义处只具备执行object方法的能力

泛型的好处:

1.类型安全,放置什么出来就是什么,不存在classcastException

2.提升可读性,编码阶段就显式知道泛型集合,泛型方法等处理的对象类型

3.代码重用,合并了同类型的处理代码

泛型擦除是什么

泛型用于编译阶段,编译后的字节码文件不包括泛型类型信息,因为虚拟机没有泛型类型对象,所欲随心都属于普通类

定义一个泛型类型,会自动提供一个对应原始类型,类型变量会被擦除,如果没有限定类型就会被替换为object,如果限定类型就会被替换为第一个限定类型

什么是反射

在运行状态中,对于任意一个类都能知道它的所有属性和方法,对于任意一个对象都能调用它的任意方法和属性,这种动态获取信息及调用对象方法的功能称为反射。缺点是破坏了封装性以及泛型约束。反射是框架的核心,Spring 大量使用反射。

反射提供的功能

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和方法;

在运行时调用任意一个对象的方法;

生成动态代理。

什么是序列化

序列化是一种对象持久化的手段。普遍应用在网络传输的场景中。对于 Java 而言,序列化主要用于对对象进行持久化操作。一般情况下,Java 对象的生命周期短于 JVM 的生命周期,随着 JVM 停止运行,Java 对象也随之消亡。但是,为了能在 JVM 停止运行后对指定对象进行持久化,并在将来的某个时刻重新读取被保存的对象,或跨 JVM 传输对象,持久化能实现上述需求。Java 在持久化对象时,会将对象的状态保存为一组字节。在反序列化时,将字节组装成对象。值得注意的是,序列化保存的的是对象的状态,即它的成员变量,而不会保存类的静态变量和被transient修饰的变量。

序列化和反序列化是什么?

Java 对象 JVM 退出时会全部销毁,如果需要将对象及状态持久化,就要通过序列化实现,将内存中的对象保存在二进制流中,需要时再将二进制流反序列化为对象。**对象序列化保存的是对象的状态,**因此属于类属性的静态变量不会被序列化。

常见的序列化有三种:

Java 原生序列化

实现 Serializabale 标记接口,Java 序列化保留了对象类的元数据(如类、成员变量、继承类信息)以及对象数据,兼容性最好,但不支持跨语言,性能一般。序列化和反序列化必须保持序列化 ID 的一致,一般使用 private static final long serialVersionUID 定义序列化 ID,如果不设置编译器会根据类的内部实现自动生成该值。如果是兼容升级不应该修改序列化 ID,防止出错,如果是不兼容升级则需要修改。

Hessian 序列化

Hessian 序列化是一种支持动态类型、跨语言、基于对象传输的网络协议。Java 对象序列化的二进制流可以被其它语言反序列化。Hessian 协议的特性:① 自描述序列化类型,不依赖外部描述文件,用一个字节表示常用基础类型,极大缩短二进制流。② 语言无关,支持脚本语言。③ 协议简单,比 Java 原生序列化高效。Hessian 会把复杂对象所有属性存储在一个 Map 中序列化,当父类和子类存在同名成员变量时会先序列化子类再序列化父类,因此子类值会被父类覆盖。

JSON 序列化

JSON 序列化就是将数据对象转换为 JSON 字符串,在序列化过程中抛弃了类型信息,所以反序列化时只有提供类型信息才能准确进行。相比前两种方式可读性更好,方便调试。

序列化通常会使用网络传输对象,而对象中往往有敏感数据,容易遭受攻击,Jackson 和 fastjson 等都出现过反序列化漏洞,因此不需要进行序列化的敏感属性传输时应加上 transient 关键字。transient 的作用就是把变量生命周期仅限于内存而不会写到磁盘里持久化,变量会被设为对应数据类型的零值。

什么是注解?什么是元注解?

注解是一种标记使类或接口附加额外信息帮助编译器和 JVM 完成一些特定功能。

Java三大注解分别是@Override @Deprecated @Suppresswarnings

  • @Override 注解表明子类中覆盖了超类中的某个方法,如果写错了覆盖形式,编译器会报错
  • @Deprecated 表明不希望别人在以后使用这个类,方法,变量等等
  • @Suppresswarnings 达到抑制编译器产生警告的目的,但是不建议使用,因为后期编码人员看不懂编译器提示的警告,不能更好的选择更好的类去完成任务

元注解是自定义注解的注解,例如:

@Target:约束作用位置,值是 ElementType 枚举常量,包括 METHOD 方法、VARIABLE 变量、TYPE 类/接口、PARAMETER 方法参数、CONSTRUCTORS 构造方法和 LOACL_VARIABLE 局部变量等。

@Rentention:约束生命周期,值是 RetentionPolicy 枚举常量,包括 SOURCE 源码、CLASS 字节码和 RUNTIME 运行时。

@Documented:表明这个注解应该被 javadoc 记录。

代理

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能同时又能起到隔离作用。这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法。

静态代理

Java 中的静态代理类似于装饰者模式,静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。

动态代理

JDK动态代理:通过Proxy类的newInstace方法获取一个动态代理对象,需要传入三个参数,被代理对象的类加载器,被代理对象实现的接口,以及一个invocationHandler调用处理器来指明具体的逻辑,相比静态代理的优势是接口声明的所有方法都被转移到invocationHandler的invoke方法集中处理

CGlib动态代理:JDK动态代理要求实现代理对象的接口,而CGlib要求继承被代理对象,如果一个类是final类不能使用CGLib代理。两种代理都在运行期生成字节码,JDK动态代理直接写字节码,而CGLib动态代理使用ASM框架写字节码,ASM的目的是生成,转换和分析以字节数组表示的已编译java类。JDK动态调用代理代理方法通过反射机制实现,而CGlib动态代理通过fastclass机制直接调用方法,它为代理类和被代理类各生成一个类,该类为代理类和被代理类的方法分配一个int参数,调用方法时可以直接定位,因此效率更高

cglib和jdk的这两者之间性能的区别

在 1.6 和 1.7 的时候,JDK 动态代理的速度要比 CGLib动态代理的速度要慢,但是并没有教科书上的10倍差距。在 JDK1.8 的时候,JDK 动态代理的速度已经比 CGLib 动态代理的速度快很多。

动态代理用多了之后对内存方面有什么影响

基于 cglib 的动态代码,此代理在设置用户缓存为 true 时不会产生内存溢出;设置为false时,会引发内存溢出。

同步/异步/阻塞/非阻塞IO的区别

同步和异步是通信机制,阻塞和非阻塞是调用状态

用户IO是用户线程发起IO请求后需要等待或轮询内核IO操作完成后才能继续执行。异步IO是用户线程发起IO请求之后可以继续执行,当内核IO操作完成后会通知用户线程,或调用用户线程注册的回调函数

阻塞 IO 是 IO 操作需要彻底完成后才能返回用户空间 。非阻塞 IO 是 IO 操作调用后立即返回一个状态值,无需等 IO 操作彻底完成

什么是BIO

BIO 是同步阻塞式 IO,JDK1.4 之前的 IO 模型。服务器实现模式为一个连接请求对应一个线程,服务器需要为每一个客户端请求创建一个线程,如果这个连接不做任何事会造成不必要的线程开销。可以通过线程池改善,这种 IO 称为伪异步 IO。适用连接数目少且服务器资源多的场景。

什么是 NIO?

NIO 是 JDK1.4 引入的同步非阻塞 IO。服务器实现模式为多个连接请求对应一个线程,客户端连接请求会注册到一个多路复用器 Selector ,Selector 轮询到连接有 IO 请求时才启动一个线程处理。适用连接数目多且连接时间短的场景。

同步是指线程还是要不断接收客户端连接并处理数据,非阻塞是指如果一个管道没有数据,不需要等待,可以轮询下一个管道。

核心组件:

Selector: 多路复用器,轮询检查多个 Channel 的状态,判断注册事件是否发生,即判断 Channel 是否处于可读或可写状态。使用前需要将 Channel 注册到 Selector,注册后会得到一个 SelectionKey,通过 SelectionKey 获取 Channel 和 Selector 相关信息。

Channel: 双向通道,替换了 BIO 中的 Stream 流,不能直接访问数据,要通过 Buffer 来读写数据,也可以和其他 Channel 交互。

Buffer: 缓冲区,本质是一块可读写数据的内存,用来简化数据读写。Buffer 三个重要属性:position 下次读写数据的位置,limit 本次读写的极限位置,capacity 最大容量。

flip 将写转为读,底层实现原理把 position 置 0,并把 limit 设为当前的 position 值。
clear 将读转为写模式(用于读完全部数据的情况,把 position 置 0,limit 设为 capacity)。
compact 将读转为写模式(用于存在未读数据的情况,让 position 指向未读数据的下一个)。
通道方向和 Buffer 方向相反,读数据相当于向 Buffer 写,写数据相当于从 Buffer 读。
使用步骤:向 Buffer 写数据,调用 flip 方法转为读模式,从 Buffer 中读数据,调用 clear 或 compact 方法清空缓冲区。

什么是 AIO?

AIO 是 JDK7 引入的异步非阻塞 IO。服务器实现模式为一个有效请求对应一个线程,客户端的 IO 请求都是由操作系统先完成 IO 操作后再通知服务器应用来直接使用准备好的数据。适用连接数目多且连接时间长的场景。

异步是指服务端线程接收到客户端管道后就交给底层处理IO通信,自己可以做其他事情,非阻塞是指客户端有数据才会处理,处理好再通知服务器。

实现方式包括通过 Future 的 get 方法进行阻塞式调用以及实现 CompletionHandler 接口,重写请求成功的回调方法 completed 和请求失败回调方法 failed。

java.io 包下有哪些流?

主要分为字符流字节流

字符流一般用于文本文件,字节流一般用于图像或其他文件

字符流包括了字符输入流 Reader字符输出流 Writer,字节流包括了字节输入流 InputStream字节输出流 OutputStream。字符流和字节流都有对应的缓冲流,字节流也可以包装为字符流,缓冲流带有一个 8KB 的缓冲数组,可以提高流的读写效率。除了缓冲流外还有过滤流 FilterReader、字符数组流 CharArrayReader、字节数组流 ByteArrayInputStream、文件流 FileInputStream 等。

对象为什么要序列化

作者:零栈工程师
链接:https://www.nowcoder.com/discuss/607451?type=0&order=7&pos=17&page=1&channel=1009&source_id=discuss_center_0_nctrack
来源:牛客网

序列化和反序列化主要在传输和解析对象的时候用,我发现一般的远程调用接口中的出入参都要能被序列化,我认为主要是多个端进行数据传输时,要提供一种机制保证大家拿到并解读出来的数据是一致的,可以用标准的serializable接口标注或者,我也遇到过很多自定义序列化方式,在另外一端用对应方法解析的,这样想我觉的除了在端上传输时需要序列化,数据在存储到本地的时候也需要序列化,保证下次使用的时候通过反序列化可以得到一样的数据

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java基础高频面试题包括以下内容: 1. 你是怎么理解面向对象的? 2. String、StringBuilder、StringBuffer的区别是什么? 3. ==与equals的区别是什么? 4. 什么是反射? 5. Java支持多继承吗? 6. 进程和线程的区别是什么? 7. 不考虑数据库的隔离性会发生什么? 8. 数据库的隔离级别有哪些? 9. 面向对象的三个基本特征是什么? 10. 访问修饰符public、private、protected以及不写时的区别是什么? 11. 给出一些代码块,判断是否能正常编译和执行。 12. 给出一些代码块,预测输出结果。 13. 如何用最有效率的方法计算2乘以8? 14. &和&&的区别是什么? 15. String是Java基本数据类型吗? 16. String类可以继承吗? 以上是一些Java基础高频面试题的例子,希望对你有帮助。 #### 引用[.reference_title] - *1* [Java基础高频面试题](https://blog.csdn.net/qsw1364941774/article/details/124499655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Java高频面试题及答案整理(会持续更新)](https://blog.csdn.net/qq_44867340/article/details/112879620)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【吐血整理】2022年Java 基础高频面试题及答案(收藏)](https://blog.csdn.net/m0_67698950/article/details/126549157)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值