Day06_JavaSE篇-程序员宅基地

技术标签: java  面试题  

文章目录

一、Java基础

1.说下面向对象四大特性

封装、继承、多态、抽象。

抽象

  • 忽略一个主题中与当前目标无关的东西,专注的注意与当前目标有关的方面.(就是把现实世界中的某一类东西,提取出来,用程序代码表示,抽象出来的一般叫做类或者接口).抽象并不打算了解全部问题,而是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一个数据抽象,而是过程抽象.
    • 数据抽象 -->表示世界中一类事物的特征,就是对象的属性.比如鸟有翅膀,羽毛等(类的属性)
    • 过程抽象 -->表示世界中一类事物的行为,就是对象的行为.比如鸟会飞,会叫(类的方法)

封装

  • 封装就是把过程和数据包围起来,对数据的访问只能通过特定的界面.如私有变量,用set,get方法获取

继承

  • 允许类的重用,子类继承父的特性,可以修改或增加新的方法使之更适合特殊的需要。因此可以说,继承为了重用父类代码,同时为实现多态性作准备.

多态

  • 多态是指允许不同类的对象对同一消息做出响应。弥补类的单继承带来的功能不足。

2.Java语言有哪些特点

  • 面向对象(封装,继承,多态)
  • 平台无关性(Java虚拟机实现平台无关性)
  • 支持多线程(多线程机制使应用程序在同一时间并行执行多项任)
  • 健壮性(Java语言的强类型机制、异常处理、垃圾的自动收集等)
  • 安全性

1.面向对象和面向过程的区别

  • 面向过程 :面向过程性能比面向对象高。因为面向对象在类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发。但是,面向过程没有面向对象易维护、易复用、易扩展。
  • 面向对象 :面向对象易维护、易复用、易扩展。 因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。但是,面向对象性能比面向过程低。

2.字符型常量和字符串常量的区别?

  • 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的若干个字符
  • 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
  • 占内存大小:字符常量只占 2 个字节; 字符串常量占若干个字节

3.装箱与拆箱

  • 装箱:将基本数据类型转换为包装器类型。
  • 拆箱:将包装类型转换为基本数据类型。

4.成员变量与局部变量的区别有哪些

在这里插入图片描述

  • 从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
  • 成员变量如果没有被赋初值:则会被自动赋予类型的默认值(一种情况例外:被 final 修饰的成员变量必须显式地赋值),而局部变量则不会被自动赋值。
  • 局部变量存储在栈里面,实例变量存储在堆里面,类变量存储在方法区里面(局长石堆)

5.对象实例与对象引用有何不同?

用new来创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。
一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)。

6.一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?

主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。

7.在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?

帮助子类完成初始化工作。

8.值传递和引用传递的区别?

public static void main(String[] args) {
    
    int num1 = 10;
    int num2 = 20;

    swap(num1, num2);

    System.out.println("num1 = " + num1);//10
    System.out.println("num2 = " + num2);//20
}

public static void swap(int a, int b) {
    
    int temp = a;
    a = b;
    b = temp;
}
    public static void main(String[] args) {
    
        int[] arr = {
     1, 2, 3, 4, 5 };
        System.out.println(arr[0]);//1
        change(arr);
        System.out.println(arr[0]);//0
    }

    public static void change(int[] array) {
    
        // 将数组的第一个元素变为0
        array[0] = 0;
    }

千万不要以为传递的参数是值就是值传递,传递的是引用就是引用传递。也不要以为传递的参数是基本数据类型就是值传递,传递的是对象就是引用传递。

值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

所以,值传递和引用传递的区别并不是传递的内容。而是实参到底有没有被复制一份给形参。

9.为什么 Java 中只有值传递?

值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

Java 程序设计语言总是采用按值调用。不论传递的参数类型是值类型还是引用类型,都会在调用栈上创建一个副本。不同的是,对于值类型来说,复制的就是整个原始值的复制。而对于引用类型来说,由于在调用栈中只存储对象的引用,因此复制的只是这个引用,而不是原始对象。

10.Java序列化中如果有些字段不想进行序列化该怎么办?

使用 transient 关键字修饰。

transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法

11.获取键盘输入常用的两种方法

方法一:通过 Scanner

Scanner input = new Scanner(System.in);
String s = input.nextLine();
input.close();

方法二:通过BufferedReader

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();

3.什么是Java程序的主类?应用程序和小程序的主类有何不同?

一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。
而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。
应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序执行的入口点。

4.访问修饰符public,private,protected,以及不写(默认)时的区别?

在这里插入图片描述

private只有当前类下可以访问,default是同包下的就可以访问,protected是子类也可以访问

(子类和父类不再同一个包中,所以你看看子类连default都访问不了,而同包中的类还可以访问)
①类的成员不写访问修饰时默认为default。
默认(default)对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。
②受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。
③Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。

5.float f=3.4;是否正确?

数据类型转换参考:Day01_入门程序、常量、变量

不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。

6.Java有没有goto?

goto 是Java中的保留字,在目前版本的Java中没有使用。(Java关键字列表中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)

7.(&和&&)的区别?

&运算符有两种用法:(1)按位与;(2)逻辑与。

&&运算符是短路与运算。

逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。
&&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&,例如在验证用户登录时判定用户名不是null而且不是空字符串,应当写为:username != null &&!username.equals(""),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的equals比较,否则会产生NullPointerException异常。注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

8.Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?

Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。

9.用最有效率的方法计算2乘以8?

2 << 3,
因为将一个数左移n 位,就相当于乘以了2 的n 次方,那么,一个数乘以8 只要将其左移3 位
即可,而位运算cpu 直接支持的,效率最高,所以,2 乘以8 等於几的最效率的方法是2 << 3。

在这里插入图片描述

10.什么是Java注释

定义:用于解释说明程序的文字

在这里插入图片描述

Java注释的作用:

在程序中,尤其是复杂的程序中,适当地加入注释可以增加程序的可读性,有利于程序的修改、调试和交流。注释的内容在程序编译的时候会被忽视,不会产生目标代码,注释的部分不会对程序的执行结果产生任何影响。

11.Java有哪些数据类型

在这里插入图片描述
基本数据类型sout打印出来的是数值, 引用数据类型sout打印出来的是对象的地址值
其中八种基本数据类型:byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double,boolean

12.final 有什么用?

用于修饰类、属性和方法;

被final修饰的类不可以被继承

被final修饰的方法不可以被重写

被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的

13.final finally finalize的区别

  • final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。
  • finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
  • finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc()
    方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。

14.String str = “i” 和String str = new String(“1”)一样吗?

不一样,因为内存的分配方式不一样。String str = "i"的方式JVM会将其分配到常量池中,而 String str = new String(“i”)JVM会将其分配到堆内存中。

15.Java 中操作字符串都有哪些类?它们之间有什么区别?

学习视频:第300集

操作字符串的类有:String、StringBuffer、StringBuilder。

String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,再将指针指向新的 String 对象,而 StringBuffer 、 StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

buffer听起来像“并发”
StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

16.Java中为什么要用 clone?

在实际编程过程中,我们常常要遇到这种情况:有一个对象 A,在某一时刻 A 中已经包含了一些有效值,此时可能会需要一个和 A 完全相同新对象 B,并且此后对 B 任何改动都不会影响到 A 中的值,也就是说,A 与 B 是两个独立的对象,但 B 的初始值是由 A 对象确定的。在 Java 语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但clone()方法是其中最简单,也是最高效的手段。

17.深克隆和浅克隆?

浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于引用数据属性,仍指向原有属性所指向的对象的内存地址。

深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

18.new一个对象的过程和clone一个对象的区别?

new 操作符的本意是分配内存。程序执行到 new 操作符时,首先去看 new 操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。

clone 在第一步是和 new 相似的,都是分配内存,调用 clone 方法时,分配的内存和原对象(即调用 clone 方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域,填充完成之后,clone方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。

19.Java中实现多态的机制是什么?

笔记链接:Day07_多态、final关键字、权限修饰符、内部类

接口定义的引用变量可以指向具体实现类实现方法,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源代码,就可以让引用变量绑定到各种不同的对象上,从而导致该引用调用的具体方法随之改变,让程序可以选择多个运行状态,这就是多态性。

(大白话:Fu类接口定义了方法eat(),Zi类定义了实现方法eat(),Fu obj = new Zi();那么obj.eat()的输出就是子类的eat()方法的输出,不用修改父类的eat()方法就可以输出新的内容)

20.谈谈你对多态的理解?

接口定义的引用变量可以指向具体实现类实现方法,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源代码,就可以让引用变量绑定到各种不同的对象上,从而导致该引用调用的具体方法随之改变,让程序可以选择多个运行状态,这就是多态性。

(大白话:Fu类接口定义了方法eat(),Zi类定义了实现方法eat(),Fu obj = new Zi();那么obj.eat()的输出就是子类的eat()方法的输出,不用修改父类的eat()方法就可以输出新的内容)

21.构造器(constructor)是否可被重写(override)?

答:构造器不能被继承,因此不能被重写,但可以被重载。

23.是否可以继承String类?

String 类是final类,不可以被继承。

补充:继承String本身就是一个错误的行为,对String类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。

24.String类的常用方法有哪些?

•splt();字符串分割,返回分割后的字符串数组。

•getBytes();返回字符串byte类型数组。

•length();返回字符串长度。

•toLowerCase();将字符串转换为小写字母。

•toUpperCase();将字符串转换为大写字母。

•substring();字符串截取。

•equals();比较字符串是否相等。

•replace();字符串替换。

•indexof();返回指定字符的的索引。

•charAt();返回指定索引处的字符。

•trim();去除字符串两端空格。

25.char型变量中能否能不能存储一个中文汉字,为什么?

char可以存储一个中文汉字,因为Java中使用的编码是Unicode,一个char 类型占2个字节(16 比特),所以放一个中文是没问题的。


位 = 比特 = bit :信息的最小单位 ,等于0或1;
字节 = byte:可表示一个英文字母、一个数字或一个符号,不能表示一个汉字;

一个字节等于八比特,1 byte =8 bit

1Byte=8bit
1 KB = 1,024 Bytes
1 MB = 1,024 KB= 1024^2 Bytes
1 GB = 1,024 MB= 1024^2 KB= 1024^3 Bytes

GBK编码,一个汉字占两个字节。UTF-8编码,通常汉字占三个字节。
编码不同,汉字所占的字节也不同;通常一个汉字是2-4个字节。

一个char 类型占2个字节(16 比特),那么一个char是否能表示一个中文?
可以,完全可以,因为Java中采用的不是GBK、UTF-8编码,而是采用的Unicode编码,
Unicode是用16位表示的,char也是16位的,Unicode字符集有包含中文,所以放一个中文完全没有问题。


26.this关键字的用法

笔记链接:Day05_关键字【Static、this、super】

  1. 在本类的成员方法中,访问本类的成员变量。(形参与成员名字重名,用this来区分)
  2. 在本类的成员方法中,访问本类的另一个成员方法。
  3. 在本类的构造方法中,访问本类的另一个构造方法。
    在第三种用法当中要注意:
    A. this(…)调用也必须是构造方法的第一个语句,唯一一个。
    B. super和this两种构造调用,不能同时使用。
1. 在本类的成员方法中,访问本类的成员变量。
public class Zi extends Fu {
    

    int num = 20;

    public void method() {
    
        int num = 30;
        System.out.println(num); // 30,局部变量
        System.out.println(this.num); // 20,本类的成员变量
        System.out.println(super.num); // 10,父类的成员变量
    }
}

2. 在本类的成员方法中,访问本类的另一个成员方法。
public class Zi extends Fu {
    

    public void methodA() {
    
        System.out.println("AAA");
    }

    public void methodB() {
    
        this.methodA(); //在本类的成员方法中,访问本类的另一个成员方法。
        System.out.println("BBB");
    }

}

3. 在本类的构造方法中,访问本类的另一个构造方法。
public class Zi extends Fu {
    

    public Zi() {
    
        this(123); // 本类的无参构造,调用本类的有参构造
    }

    public Zi(int n) {
    
        this(1, 2); //在本类的构造方法中,访问本类的另一个构造方法。
    }
    
    public Zi(int n, int m) {
    
    
    }
}

27.super关键字的用法

笔记链接:Day05_关键字【Static、this、super】

  • 在子类的成员方法中,访问父类的成员变量。
  • 在子类的成员方法中,访问父类的成员方法。
  • 在子类的构造方法中,访问父类的构造方法。
public class Fu {
    
    public Fu() {
    
        System.out.println("父类的无参数构造方法!");
    }
}

public class Zi extends Fu {
    
    public Zi() {
    
        super(); // 不管你写不写这行代码,系统都默认给你带上了
        System.out.println("子类构造方法!");
    }
}

public class Demo01Constructor {
    
    public static void main(String[] args) {
    
        Zi zi = new Zi();
    }
}

输出:
父类的无参数构造方法!
子类构造方法!

28.this与super的区别

  • super:它引用当前对象的直接父类中的成员
  • this:它代表当前对象名(如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
  • super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
  • super()和this()均需放在构造方法内第一行,且只能使用一个。
  • this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。

29.static存在的主要意义

①创建独立于具体对象的域变量或者方法。 以致于即使没有创建对象,也能使用属性和调用方法 !
②static块可以用来优化程序性能,因为:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

30.static的独特之处

独立于对象 且 优先于对象:

  1. 被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法 不属于任何一个实例对象,而是被类的实例对象所共享。
  2. 被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

31.static应用场景

被static修饰的就是被整个类所共享的

  1. 修饰类【只能修饰内部类也就是静态内部类】
  2. 修饰成员方法
  3. 修饰成员变量
  4. 静态代码块
  5. 静态导包

32.static注意事项

1、静态只能访问静态。 2、非静态既可以访问非静态的,也可以访问静态的。

在这里插入图片描述

33.break ,continue ,return 的区别及作用

break 结束当前的循环体

continue 跳出本次循环,继续执行下次循环

return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)

34.在Java中定义一个不做事且没有参数的构造方法的作用

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

35.构造方法有哪些特性?

名字与类名相同;

没有返回值,但不能用void声明构造函数;

生成类的对象时自动执行,无需调用。

36.静态变量和实例变量区别

静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。

实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。

37.静态方法和实例方法有何不同?

静态方法和实例方法的区别主要体现在两个方面:

1.在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。

2.静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制

38.什么是方法的返回值?返回值的作用是什么?

方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。

返回值的作用:接收出结果,使得它可以用于其他的操作!

39.什么是内部类?

在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是 内部类 。内部类本身就是类的一个属性,与其他属性定义方式一致。

40.内部类的分类有哪些

内部类可以分为四种: 成员内部类、局部内部类、匿名内部类和静态内部类 。

41.Java中异常分为哪些种类?/ Java中异常处理机制是什么?

按照异常需要处理的时机分为编译时异常 和运行时异常。

(1)编译时异常Java程序必须显式处理,如果程序没有处理就会发生错误无法编译。对编译时异常处理方法有两种:

●第一种:当前方法知道如何处理该异常,则用try…catch块来处理该异常。

●第二种:当前方法不知道如何处理,则在定义该方法时声明抛出该异常。(涉及到throw和throws的区别)

(2)运行时异常只有当代码在运行时才发行的异常,编译的时候不需要try…catch。

throw和throws的区别?

throw和throws作为Java中两种异常抛出关键字,虽然两个长的很像,但是却有着很大的区别。

区别1:
 throws:
     跟在方法声明后面,后面跟的是异常类名
 
 throw:
    用在方法体内,后面跟的是异常类对象名   
public static void method() throws ArithmeticException {
    // 跟在方法声明后面,后面跟的是异常类名
        int a=10;
        int b=0;
        if(b==0) {
    
        	throw new ArithmeticException();用在方法体内,后面跟的是异常类对象名 
        }else {
    
        	System.out.println(a/b);
        }
	}
}
区别2:
throws:
    可以跟多个异常类名,用逗号隔开
 
 throw:
   只能抛出一个异常对象名 
	public static void method() throws ArithmeticException,Exception {
    //跟多个异常类名,用逗号隔开
        int a=10;
        int b=0;
        if(b==0) {
    
        	throw new ArithmeticException();// 只能抛出一个异常对象名
        }else {
    
        	System.out.println(a/b);
        }
	}
}
区别3:
throws:
     表示抛出异常,由该方法的调用者来处理
 
 throw:
    表示抛出异常,由该方法体内的语句来处理
public class throwandthrows {
    
	public static void main(String[] args) {
    
		try {
    
		method();//由该方法的调用者来处理
	}catch (ArithmeticException e) {
    
		   e.printStackTrace();
	}
	}

	public static void method() throws ArithmeticException {
    
        int a=10;
        int b=0;
        if(b==0) {
    
        	throw new ArithmeticException();//由该方法体内的语句来处理
        }else {
    
        	System.out.println(a/b);
        }
	}
}
区别4:
throws:
     throws表示有出现异常的可能性,并不一定出现这些异常
 
 throw:
    throw则是抛出了异常,执行throw一定出现了某种异常

我们向上面例子代码里throws一个IndexOutOfBoundsException异常,编译发现并没有报错,这就体现了throws表示有出现异常的可能性

public class throwandthrows {
    
	public static void main(String[] args) {
    
		try {
    
		method();
	}catch (ArithmeticException e) {
    
		   e.printStackTrace();
	}
	}

	public static void method() throws ArithmeticException,IndexOutOfBoundsException {
    
        int a=10;
        int b=0;
        if(b==0) {
    
        	throw new ArithmeticException();
        }else {
    
        	System.out.println(a/b);
        }
	}
}

45.抽象类和接口(Java7)的区别

学习文档:Day06_重写和重载、抽象类、接口

1.抽象类里面可以有抽象方法也可以存在其它非抽象方法,但是接口里面只能存在抽象方法(也就是被public abstract修饰的)
(ps:在jdk8和jdk9以后接口里面才有了默认方法、静态方法、私有方法)

2.抽象类中的成员变量可以是各种类型的,而接口中只能有常量(也就是要被public static final修饰的 );

3.一个类只能继承一个抽象类,而一个类却可以实现多个接口。

4…最后就是语义上的区别:什么时候用抽象类?抽象类描述的往往是我们平时能够接触到的概念,比如“动物”、“植物”、“食物”;
什么时候用接口?接口描述的某些共同事务之间所具有的共同特征,比如“会飞的”(蜻蜓会飞、奥特曼也会飞)

46.Java 8的接口新增了哪些特性?

jdk8: 增加了default方法和static方法,这2种方法可以有方法体。
jdk9:接口允许 以 private 修饰的方法

1.关于抽象类的温习:

在这里插入图片描述

子类必须覆盖重写抽象父类当中所有的抽象方法。
一个抽象类不一定含有抽象方法,只要保证抽象方法所在的类是抽象类,即可。

public abstract class Animal {
    

    // 这是一个抽象方法,代表吃东西,但是具体吃什么(大括号的内容)不确定。
    public abstract void eat();

    // 这是普通的成员方法
    public void normalMethod() {
    
		System.out.println("我不是抽象方法但我可以在抽象类中");
    }
}

总之:抽象类可以有抽象方法,也可以有普通方法;子类继承了抽象的父类,那么子类就必须把父类里面的抽象方法都重写一遍(父类中的普通方法就可以不重写)

2.关于接口的温习:

在这里插入图片描述
接口的名字是MyInterAbstract,那么实现了这个接口的类名应该是MyInterAbstractImpl(即“接口名+Impl”)。

接口内容可以写什么呢?

  • 可以写抽象方法
    • 可以写抽象方法。接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract,当然,可以省略。
    • 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法。
  • 也可以写默认方法
    • 默认的方法会被实现该接口的类继承下去。假如你写了一个接口和它的实现类,假如现在接口升级了,多了一个新功能,多了一个抽象方法A(),那么接口的实现类就得覆盖重写接口中的改抽象方法;而如果方法A()弄成默认方法,那么接口的实现类就没必要覆盖重写,方法A()会被继承下去,实现了对接口实现类的0改动。
  • 也可以写静态方法(A接口有个私有方法eat(),Aimpl是A接口的实现类,调用eat()方法不能是Aimpl.eat(),只能是A.eat();)
  • 也可以写私有方法(普通私有方法,解决多个默认方法之间重复代码问题)在这里插入图片描述
  • 也可以写常量(见8.接口的常量)
    在这里插入图片描述

47.重写和重载的区别

重写(Override):方法的名称一样,参数列表【也一样】,返回值类型不能改变。
重载(Overload):方法的名称一样,参数列表【不一样】,返回值类型可以改变。
重写就是覆盖重写,方法名、参数、返回值类型都没有变,外壳不变,核心重写。
每个重载的方法都必须有一个独一无二的参数类型列表。
重载在同一个类中发生,重写在子类父类中发生。

53.静态代理和动态代理

学习文档:Day10_Filter和Listener

(1)为什么需要代理?

代理可以对一些功能进行增强,比如增强参数列表、增强返回值类型、增强方法体执行逻辑

Proxy代理模式主要解决的问题是:在直接访问对象时带来的问题,为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

(2)静态代理和动态代理的区别

①静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时运用反射机制动态创建而成。
②静态代理的效率相对动态代理来说相对高一些,但是静态代理代码冗余大,一单需要修改接口,代理类和委托类都需要修改。
③静态代理只服务于一种类型的对象,如果要服务多类型的对象,势必要为每一种对象都进行代理,这样程序开发中必然会产生许多的代理类。对于动态代理,原接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理。

1.静态代理

在这里插入图片描述

在这里插入图片描述

2.动态代理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)动态代理实现步骤:
  1. 代理对象和真实对象实现相同的接口
  2. 代理对象 = Proxy.newProxyInstance();
  3. 使用代理对象调用方法。
  4. 增强方法
(4) 增强方式:
  1. 增强参数列表
  2. 增强返回值类型
  3. 增强方法体执行逻辑

54.JDK动态代理和CGLIB动态代理的区别

学习文档:day03_Spring—面向切面编程aop

Spring AOP使用动态代理技术在运行期织入增强代码。使用两种代理机制:基于JDK的动态代理(JDK本身只提供接口的代理)和基于CGlib的动态代理。

(1)JDK的动态代理
其代理对象必须是某个接口的实现, 它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理.只能对实现接口的类生成代理,而不能针对类。

(2)CGLib
CGLib采用底层的字节码技术,为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类的调用方法,并顺势织入横切逻辑.它运行期间生成的代理对象是目标类的扩展子类.所以无法通知final、private的方法,因为它们不能被覆写.是针对类实现代理,主要是为指定的类生成一个子类,覆盖其中方法。

这里是引用

55.Spring在选择用JDK还是CGLiB的依据:

(1)当Bean实现接口时,Spring就会用JDK的动态代理

(2)当Bean没有实现接口时,Spring使用CGlib是实现

(3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)

25.Spring AOP 实现原理

实现AOP的技术,主要分为两大类:
一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

Spring AOP使用动态代理技术在运行期织入增强代码。使用两种代理机制:基于JDK的动态代理(JDK本身只提供接口的代理)和基于CGlib的动态代理。

(1)JDK的动态代理
其代理对象必须是某个接口的实现, 它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理.只能对实现接口的类生成代理,而不能针对类。

(2)CGLib
CGLib采用底层的字节码技术,为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类的调用方法,并顺势织入横切逻辑.它运行期间生成的代理对象是目标类的扩展子类.所以无法通知final、private的方法,因为它们不能被覆写.是针对类实现代理,主要是为指定的类生成一个子类,覆盖其中方法。

11.Java 异常框架

在这里插入图片描述
在这里插入图片描述

56.自定义异常在生产中如何应用

1、为什么需要自定义异常类
一些异常都是 Java 内部定义好的,但是实际开发中也会出现很多异常,这些异常很可能在JDK中没有定义过,例如年龄负数问题,考试成绩负数问题,这时就需要我们自定义异常。在开发中根据自己业务的异常情况来定义异常类就是自定义异常。

2、异常类如何定义
(1)自定义一个编译器异常:自定义类 并继承 java.lang.Exception
(2)自定义一个运行时期的异常类:自定义类,并继承于 java.lang.RuntimeException。

建议:保留两种构造器的形式
①无参构造
②带给父类的message属性赋值的构造器

注意:
自定义异常类,必须的继承Exception或者RuntimeException
继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try…catch;
继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理)
 
示例代码:

@Setter
@Getter
@ToString
public class Student {
    

    private int id;
    private String name;
    private String age;

    public Student(int id, String name, String age) {
    
        this.id = id;
        this.name = name;
        this.age = age;
    }
}
/**
 * 自定义异常类
 */
public class StudentExcePtion extends Exception{
    
    public StudentExcePtion(String messagee) {
    
        super(messagee);
    }

}
public class Test implements StudentManager{
    

    static int total = 2;  //总人数
    static int count = 0; //当前人数
    Student[] st = new Student[total];
    @Override
    public void add(Student stu) throws StudentExcePtion {
    

        if(count<total){
    
            st[count] = stu;
            count++;
        }else {
    
            throw new StudentExcePtion("越界了");
        }
    }

    public static void main(String[] args) throws StudentExcePtion {
    
        Test sm = new Test();

        Student s1 = new Student(01, "tom1", "21");
        Student s2 = new Student(02, "tom2", "22");
        Student s3 = new Student(03, "tom3", "23");

        sm.add(s1);
        sm.add(s2);
        sm.add(s3);
    }
}

57.怎样声明一个类不会被继承,什么场景下会用

如果一个类被final修饰,此类不可以有子类,不能被其它类继承,如果一个中的所有方法都没有重写的需要,当前类没有子类也罢,就可以使用final修饰类。
以Math类为例:

这里是引用

59.什么是ForkJoin框架 适用场景

虽然目前处理器核心数已经发展到很大数目,但是按任务并发处理并不能完全充分的利用处理器资源,因为一般的应用程序没有那么多的并发处理任务。基于这种现状,考虑把一个任务拆分成多个单元,每个单元分别得到执行,最后合并每个单元的结果。

Fork/Join框架是一个用于并行执行任务的框架,是一个把大任务分割成若干小任务,最终汇总每个小任务结果得到大任务结果的框架。
在这里插入图片描述

1.ForkJoin 特点:工作窃取!

这里是引用

线程池中的每个线程都有自己的工作队列(PS,这一点和ThreadPoolExecutor不同,ThreadPoolExecutor是所有线程公用一个工作队列,所有线程都从这个工作队列中取任务),当自己队列中的任务都完成以后,会从其它线程的工作队列中偷一个任务执行,这样可以充分利用资源。

A线程处理完了自己队列的任务,B线程的队列里还有很多任务要处理。 A想过去帮忙,但是如果两个线程访问同一个队列,会产生竞争,所以A想了一个办法,从双端队列的尾部拿任务执行。而B线程永远是从双端队列的头部拿任务执行。

  • 工作窃取算法的优点:利用了线程进行并行计算,减少了线程间的竞争。
  • 工作窃取算法的缺点:任务争夺问题

2.如何使用ForkJoin?

1.通过 ForkJoinPool 来执行

2.计算任务 execute(ForkJoinTask<?> task)

3.计算类要去继承 ForkJoinTask

1.写一个ForkJoin类

public class ForkJoinDemo extends RecursiveTask<Long> {
    

    private Long start;
    private Long end;

    // 临界值(start-end小于它那就使用普通的计算方式,如果start-end大于临界值就是用ForkJoin的方式)
    private Long temp = 10000L;

    public ForkJoinDemo(Long start, Long end) {
    
        this.start = start;
        this.end = end;
    }

    // 计算方法
    @Override
    protected Long compute() {
    
        if ((end-start)<temp){
    
            Long sum = 0L;
            for (Long i = start; i <= end; i++) {
    
                sum += i;
            }
            return sum;
        }else {
     // forkjoin 递归
            long middle = (start + end) / 2; // 中间值
            ForkJoinDemo task1 = new ForkJoinDemo(start, middle);// 拆分任务
            task1.fork(); // 把任务压入线程队列
            ForkJoinDemo task2 = new ForkJoinDemo(middle+1, end);// 拆分任务
            task2.fork(); // 把任务压入线程队列

            return task1.join() + task2.join();
        }
    }
}

2.测试类

public class Test {
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
        test3();
    }

    // 普通程序员(用for循环完成1到10亿的累和)
    public static void test1(){
    
        Long sum = 0L;
        long start = System.currentTimeMillis();//开始时间
        for (Long i = 1L; i <= 10_0000_0000; i++) {
    
            sum += i;
        }
        long end = System.currentTimeMillis();//结束时间
        System.out.println("sum="+sum+" 时间:"+(end-start));//用时6105
    }

    // 会使用ForkJoin
    public static void test2() throws ExecutionException, InterruptedException {
    

        long start = System.currentTimeMillis();

        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinDemo(0L, 10_0000_0000L);
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);// 提交任务
        Long sum = submit.get();//获取到任务的返回值

        long end = System.currentTimeMillis();

        System.out.println("sum="+sum+" 时间:"+(end-start));//用时3876
    }

    //用Stream并行流 (),效率会高更多
    public static void test3(){
    
        long start = System.currentTimeMillis();
        long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);//用时197
        long end = System.currentTimeMillis();
        System.out.println("sum="+"时间:"+(end-start));
    }
}

二、Java8新特性

1.Java 8 新特性简介:

  1. 增加了Lambda 表达式

  2. 强大的 Stream API(集合数据的操作)

  3. 最大化的减少空指针 异常:Optional 类 的使用

  4. 接口的新特性

  5. 注解的新特性

  6. 集合的底层 源码实现

  7. 新日期时间的 api

属性 含义
Instant 代表的是时间戳
LocalDate 代表日期,比如2020-01-14
LocalTime 代表时刻,比如12:59:59
LocalDateTime 代表具体时间 2020-01-12 12:22:26
ZonedDateTime 代表一个包含时区的完整的日期时间,偏移量是以UTC/ 格林威治时间为基准的
Period 代表时间段
ZoneOffset 代表时区偏移量,比如:+8:00
Clock 代表时钟,比如获取目前美国纽约的时间

3.Java8支持函数编程是什么意思?

在Java 8之前,所有东西都是面向对象的。除了原语之外,java中的 所有内容都作为对象存在。对方法/函数的所有调用都是使用对象或类引用进行的。

方法/功能本身并不是独立存在的。

使用Java 8,引入了函数式编程。所以我们可以使用匿名函数。Java是一种一流的面向对象语言。除了原始数据类型之外,Java中的所有内容都是一个对象。即使是一个数组也是一个对象。每个类都创建对象的实例。没有办法只定义一个独立于Java的函数/方法。无法将方法作为参数传递或返回该实例的方法体。

4.Java 8中的可选项是什么?

Java 8引入了一个新的容器类java.util.Optional 。如果该值可用,它将包装一个值。如果该值不可用,则应返回空的可选项。因此它代表空值,缺失值。这个类有各种实用方法,如isPresent(),它可以帮助用户避免使用空值检查。由于不直接返回值,而是返回包装器对象,所以用户可以避免空指针异常。

5.hashMap原理,java8做的改变

  1. JDK1.7的时候使用的是数组+ 单链表的数据结构。但是在JDK1.8及之后时,使用的是数组+链表+红黑树的数据结构(当链表的深度达到8的时候,也就是默认阈值,就会自动扩容把链表转成红黑树的数据结构来把时间复杂度从O(n)变成O(logN)提高了效率)
  2. 在1.7是采用表头插入法插入链表,1.8采用的是尾部插入法。
    因为JDK1.7是用单链表进行的纵向延伸,当采用头插法时会容易出现逆序且环形链表死循环问题。但是在JDK1.8之后是因为加入了红黑树使用尾插法,能够避免出现逆序且链表死循环的问题。
  3. 在1.7扩容时需要重新计算哈希值和索引位置(计算hashcode --> 做扰动处理 --> 计算 h & length-1 ),
    在1.8并不重新计算哈希值,巧妙地采用和扩容后容量进行&操作来计算新的索引位置,这样得到的新索引位置=(原位置)或(原位置+旧容量)。
  4. 在JDK1.7的时候是先扩容后插入的,这样就会导致无论这一次插入是不是发生hash冲突都需要进行扩容,如果这次插入的并没有发生Hash冲突的话,那么就会造成一次无效扩容,但是在1.8的时候是先插入再扩容的,优点其实是因为为了减少这一次无效的扩容,原因就是如果这次插入没有发生Hash冲突的话,那么其实就不会造成扩容,但是在1.7的时候就会急造成扩容

6.解释Java 8-中间操作与终端操作?

流操作可以分为两部分:

  • 中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。中间操作返回类型为Stream(流类型);它们不会产生结果,因为这些操作在终端操作执行之前不会调用。比如map (mapToInt, flatMap 等)、filter、distinct、sorted、peek、limit、skip、parallel、sequential、unordered。
  • 当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终止操作。终止操作将返回一个执行结果,这就是你想要的数据。
    终端操作返回类型非流类型。比如:forEach、forEachOrdered、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator。

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理!而在终止操作时一次性全部处理,称作“惰性求值”。

在这里插入图片描述

7.在Jdk1.8中的stream有用过吗,详述一下stream的并行操作原理?stream并行的线程池是从哪里来的?

Day28_Stream流

Stream API借助于同样新出现的Lambda表达式。同时,它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。

流操作可以分为两部分:

  • 中间操作仍然会返回一个流对象,因此多个中间操作可以串连起来形成一个流水线。中间操作返回类型为Stream(流类型);它们不会产生结果,因为这些操作在终端操作执行之前不会调用。比如map (mapToInt, flatMap 等)、filter、distinct、sorted、peek、limit、skip、parallel、sequential、unordered。
  • 当所有的中间操作完成后,若要将数据从流水线上拿下来,则需要执行终止操作。终止操作将返回一个执行结果,这就是你想要的数据。
    终端操作返回类型非流类型。比如:forEach、forEachOrdered、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator。

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理!而在终止操作时一次性全部处理,称作“惰性求值”。

stream并行原理: 其实本质上就是在ForkJoin上进行了一层封装,将Stream 不断尝试分解成更小的split,然后使用fork/join 框架分而治之, parallize使用了默认的ForkJoinPool.common 默认的一个静态线程池.

7.什么是Lambda表达式?

Lambda Expression可以定义为允许用户将方法作为参数传递的匿名函数。Lambda函数没有访问修饰符(私有,公共或受保护),没有返回类型声明和没有名称。

Lambda表达式允许用户将“函数”传递给代码。所以,假设我们的代码具有一些复杂的循环/条件逻辑或工作流程。使用lambda表达式,在那些有难度的地方,可以得到很好的解决。

8.Lambda函数的优缺点:

优点:
1、代码更加简洁,更少的代码行。
2、效率更高。通过使用具有多核的CPU,用户可以通过使用lambda并行处理集合来利用多核CPU。
2、减少匿名内部类的创建,节省资源;

缺点:
1、不熟悉Lambda表达式的语法的人,不太容易看得懂;
2、虽然代码更加简洁,但可读性差,不利于维护;

9.什么是Java8中的MetaSpace?它与PermGen Space有何不同?

使用JDK8时,permGen空间已被删除。那么现在将元数据信息存储在哪里?此元数据现在存储在本机内存中,称为“MetaSpace”。该内存不是连续的Java堆内存。
整个永久代有一个 JVM 本身设置固定大小上线,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,并且永远不会出现java.lang.OutOfMemoryError。你可以使用-XX:MaxMetaspaceSize 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。-XX:MetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。

10.是什么使Java SE 8优于其他?

Java SE 8具有以下功能,使其优于其他功能:

它具有更易读和简洁的代码。

它编写并行代码。它提供了更多可用的代码。

它具有改进的性能应用程序。

它支持编写包含促销的数据库。

11.Lambda表达式的参数列表与Lambda箭头运算符有何不同?

Lambda表达式可以一次携带零个,一个或甚至多个参数。

另一方面,Lambda箭头运算符使用图标“->”将Lambda表达式拆分成两部分;

  • 左侧: Lambda表达式的参数列表,对应的是接口中抽象方法的参数列表;
  • 右侧: Lambda表达式中所需要执行的功能(Lambda体),对应的是对抽象方法的实现;(函数式接口(只能有一个抽象方法))

三、Java IO

Day25、IO流小结

回顾JavaIO

1.各种流

    字节流----FileInputStreamFileOutputStream
    字符流----FileReaderFileWriter
    缓冲流----BufferedInputStreamBufferReader
	转换流----InputStreamReaderOutputStreamWriter
    序列化流--ObjectOutputStreamObjectInputStream
	(巧计:InputStream是字节流家族的,Reader是字符流家族的,InputStreamReader既含字节流又含字符流所以就是来回切换的流,就是转换流)

2.流之间的继承关系

字节输入流、字节输出流
FileInputStream extends InputStream
FileOutputStream extends OutputStream

字符输入流、字符输出流(字符流家族一定含有reader或writer)
FileReader extends InputStreamReader extends Reader
FileWriter extends OutputStreamWriter extends Writer

缓冲流
BufferedOutputStream extends OutputStream
BufferedInputStream extends InputStream
BufferedWriter extends Writer
BufferedReader extends Reader

转换流(用来编码的)
InputStreamReader extends Reader
OutputStreamWriter extends Writer
    
序列化流:构造方法的参数是字节流
ObjectOutputStream extends OutputStream
ObjectInputStream extends InputStream    

1.Java 中有几种类型的流?

(1)按照流的方向:输入流(inputStream)和输出流(outputStream);
(2)按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。

  • 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
  • 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

(3)按照处理数据的单位: 字节流和字符流。

2.什么是节点流,什么是处理流,它们各有什么用处,处理流的创建有什么特征?

1.节点流 直接与数据源相连,用于输入或者输出

2.处理流:在节点流的基础上对之进行加工,进行一些功能的扩展

3.处理流的构造器必须要 传入节点流的子类

节点流:
    字节流----FileInputStreamFileOutputStream
    字符流----FileReaderFileWriter

处理流:
    缓冲流----BufferedInputStreamBufferReader
	转换流----InputStreamReaderOutputStreamWriter
    序列化流--ObjectOutputStreamObjectInputStream

3.什么是 java序列化?

序列化:把Java对象转换为字节序列的过程。
  反序列化:把字节序列恢复为Java对象的过程。
  
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。只能将支持 java.io.Serializable 接口的对象写入流中。

4.如何实现 java 序列化?

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("10_IO\\person.txt"));
        oos.writeObject(new Person("小美女",18));

序列化的实现,将需要被序列化的类实现Serializable 接口,该接口没有需要实现的方法, implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如: FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着使用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将参数为 obj 的对象写出(即保存其状态),要恢复的话则用输入流。

5.字节流和字符流的区别?

①字节流主要是操作 byte 类型数据,字节流处理byte或byte数组;
字符流处理的单元为 2 个字节的 Unicode 字符,字符流处理char或char数组或String字符串。

②字符流是由 Java 虚拟机将字节转化为 2 个字节的 Unicode 字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点。在程序中一个字符等于两个字节,java 提供了 Reader、Writer 两个专门操作字符流的类。

②字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。

6.PrintStream、PrintWriter、BufferedWriter的比较?

1.PrintStream是OutputStream的子类,PrintWriter是Writer的子类。对于使用print系列方法的场合,二者非常相像。
PrintStream和PrintWriter的autoflushing机制有点不同,前者在输出byte数组、调用println方法、输出换行符或者byte值10(即\n)时自动调用flush方法,后者仅在调用println方法时发生autoflushing。
System.out.println()就是调用的PrintStream的println方法。这里的out就是printstream对象,println方法会自动清空缓存

2.BufferedWriter字符缓冲输出流,只能对字符流进行操作。如果要对字节流操作,则使用BufferedInputStream。
不用缓冲流是读一个返回一个,现在有了缓冲流都是把读到的字节或字符先存在数组缓冲区,再一次返回多个字节或字符。
它通过newLine()进行换行操作。BufferedWriter中的字符流必须通过调用flush方法才能把内部缓冲区中的数据,刷新到文件中。

7.流一般需要不需要关闭,如果关闭的话在用什么方法,一般要在哪个代码块里面关闭比较好,如果有多个流互相调用传入是怎么关闭的?

1.流一旦打开就必须关闭,使用close方法

2.放入finally语句块中(finally 语句一定会执行)

3.多个流互相调用只关闭最外层的流

11.同步与异步

同步就是B任务依赖A任务时,只有A任务完成后,B任务才能执行。这是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。
异步就是B任务依赖A任务时,A任务执行时B任务也会立即执行。至于被依赖的A任务最终是否真正完成,B也无法确定,所以它是不可靠的任务序列。

举例:
同步和异步关注的是消息通信机制
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

12.阻塞与非阻塞

阻塞与非阻塞主要是从 CPU 的消耗上来说的,阻塞就是 A任务执行时,B要阻塞等待。

非阻塞就是CPU在执行A任务时,也可以执行其它任务(比如B任务)。

虽然表面上看非阻塞的方式可以明显的提高 CPU 的利用率,但是也带了另外一种后果就是系统的线程切换增加。增加的 CPU 使用时间能不能补偿系统的切换成本需要好好评估。

举例:
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。

13.同步、异步、阻塞、非堵塞

在这里插入图片描述

1.小明把水壶放到火上,然后在那傻等水开。(同步阻塞)

2.小明把水壶放到火上,然后去客厅看电视,时不时的去厨房看看水开没有。(同步非阻塞)

小明还是觉得自己有点傻,于是变高端了,买了一个水烧开了会响的水壶。水开之后能大声的发出响声提示人水开了。。。

3.小明把响水壶放到火上,然后在那傻等水开。(异步阻塞)

4.小明把响水水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去处理。(异步非阻塞)

所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。
虽然都能干活,但响水壶可以在自己完工之后,提示小明水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中) ,造成小明效率的低下。

所谓阻塞非阻塞,仅仅对于小明而言。傻等的小明,阻塞;看电视的小明,非阻塞。
情况1和情况3中小明就是阻塞的,有人喊他都不知道。虽然3中响水壶是异步的,可对于立等的小明没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。

同步异步:同步是指一个时间点只能有一个程序在占用CPU,而异步是指可以有多个程序并行(可以很好的利用操作系统的多核)

阻塞非阻塞:阻塞是指操作系统发出一个调用/操作之后,必须等到此调用返回结果后才返回。而非阻塞是指在操作系统发出一个调用/操作后,不用等到执行完毕得到结果才返回,而是立即返回,然后可以执行其他的调用/操作。

14.通道是个什么意思?

通道是一种管理I/O操作的控制器,它使主机(CPU和内存)与I/O操作之间达到更高的并行程度。

15.缓冲区是什么意思?

缓冲区实质上是一个数组。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。

种类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer

16.IO多路复用的底层原理

这一块严重涉及到计算机网络的知识,还有那些BIO、NIO、AIO都需要你看视频去专题掌握

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45014721/article/details/119852815

智能推荐

稀疏编码的数学基础与理论分析-程序员宅基地

文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...

EasyGBS国标流媒体服务器GB28181国标方案安装使用文档-程序员宅基地

文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档

【Web】记录巅峰极客2023 BabyURL题目复现——Jackson原生链_原生jackson 反序列化链子-程序员宅基地

文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子

一文搞懂SpringCloud,详解干货,做好笔记_spring cloud-程序员宅基地

文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud

Js实现图片点击切换与轮播-程序员宅基地

文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换

tensorflow-gpu版本安装教程(过程详细)_tensorflow gpu版本安装-程序员宅基地

文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装

随便推点

物联网时代 权限滥用漏洞的攻击及防御-程序员宅基地

文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者

Visual Odometry and Depth Calculation--Epipolar Geometry--Direct Method--PnP_normalized plane coordinates-程序员宅基地

文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be ​ and th_normalized plane coordinates

开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先抽取关系)_语义角色增强的关系抽取-程序员宅基地

文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景​ 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取

10个顶尖响应式HTML5网页_html欢迎页面-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面

计算机二级 考试科目,2018全国计算机等级考试调整,一、二级都增加了考试科目...-程序员宅基地

文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思

conan简单使用_apt install conan-程序员宅基地

文章浏览阅读240次。conan简单使用。_apt install conan