Java面试题总结(Java基础知识,JVM)

1、基本数据类型

位(bit)音译比特,计算机内部数据存储的最小单位,网络带宽就是b(位)

字节(byte)8位,大写的B,

int是几个字节,4个字节,一个字节是8位,byte是一个字节,取值范围是正 00000000 0  到 01111111 127 负 10000000 -128 到11111111 -1

以下代码会返回-56,因为456的二进制表示是111001000,然后由于int是32位的二进制,高位补0,在计算机中,即为00000000000……111001000,int转成byte的时候,计算机只保留最后8位,即11001000,最高位是1,表示是一个负数,负数都是以补码保存,其反码为00110111,末尾加一即为补码即00111000,即56,所以结果是-56

public class A {
 public static void main(String[] args) {
  int b = 456;
  byte test = (byte) b;
  System.out.println(test);
 }
}

基本类型的包装类基本都实现了常量池技术,即 Byte,Short,Integer,Long,Character,Boolean,前面四种包装类默认创建了数值[-128,127]的相应类型的缓存数据,

Character创建了[0,127]数值的缓存数据,Boolean直接返回True or False ,如果超出对应范围仍然会创建新的对象

2、方法和函数

方法是值传递,即按值调用,方法得到的是所有参数值的一个拷贝,如果是基本数据类型那就是值的拷贝,如果是对象引用那就是引用的拷贝,但是和原引用指向同一个对象,因此可以修改对象的属性,但是无法让这个对象参数引用一个新的对象

匿名内部类使用的形参必须是final修饰:因为匿名内部类编译成功以后会产生一个class文件,和外部类并不是同一个文件,会通过自身的构造器对参数备份,实际使用的并不是外部传入的参数,为了避免引用值发生改变,比如被外部类修改,而导致和内部类得到的值不一致,因此用final来修饰来让该引用不可改变

String 不可变

String类中维护了一个char数组,并且用final修饰了,private final char value[] 因此是不可变的,可以理解为常量,每次对String类型的值进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象,String类也用final修饰了,因此也是不可以被继承的

StringBuffer和StringBuilder是可变的,没有final修饰,不会生成新的对象,其中StringBuffer加了同步锁,所以是线程安全的

final:修饰的类不能被继承,修饰的方法不能被重写,修饰的变量是常量,如果是基本数据类型,则值不能更改,如果是引用,则不能再让其指向另外一个对象

3、常量池

方法区:方法区和JAVA堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 
运行时常量池:它是方法区的一部分,Class文件中除了有类的版本、方法、字段等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分信息在类加载时进入方法区的运行时常量池中。 
方法区的内存回收目标是针对常量池的回收及对类型的卸载。

java 的方法调用有两类,动态方法调用与静态方法调用。

  • 静态方法调用是指对于类的静态方法的调用方式,是静态绑定的
  • 动态方法调用需要有方法调用所作用的对象,是动态绑定的

方法表是实现动态调用的核心。上面讲过方法表存放在方法区中的类型信息中。为了优化对象调用方法的速度,方法区的类型信息会增加一个指针,该指针指向一个记录该类方法的方法表,方法表中的每一个项都是对应方法的指针。

4、stream

stream是java8中的新特性,其实 Stream 就是以 Lambda 和方法引用为基础,封装的简单易用、函数式风格的 API。

lambda表达式是一个匿名函数,即没有函数名的函数,可以表示闭包,简化了匿名内部类的形式,和匿名内部类的区别就是匿名内部类在编译之后会创建一个新的匿名内部类出来,而 Lambda 是调用 JVM invokedynamic指令实现的,并不会产生新类。

方法引用:方法引用的出现,使得我们可以将一个方法赋给一个变量或者作为参数传递给另外一个方法。::双冒号作为方法引用的符号

是函数式接口,函数式接口本质上还是一个接口,但是它是一种特殊的接口:其实就是通过闭包作为参数定义接口内方法的参数,以及方法体。
一个函数式的接口,必须使用@FunctionalInterface进行修饰。函数式接口其实就是定义不同参数和返回值类型的闭包。

使用形式:

//(1)定义一个函数式接口 Function<T, R> -T作为输入,返回的R作为输出
@FunctionalInterface
interface TestFunction<T, R> {
    R test(T from);
}

// 使用该接口
 TestFunction<String,String> function = (x) -> {System.out.print(x);return "Function";};
 System.out.println(function.test("hello world"));

stream流被分为中间和终端操作,继承了AbstractPipeline也就是管道,管道是通过双端链表构造的

Stream中将操作抽象化为stage 每个stage 也就是一个AbstractPipeline,每个stage 相当于一个双向链表的节点  ,每个节点都保存Head然后保存着上一个和下一个

这个双向链表就构成了整个流水线

image_5b7a5140_1a8b

sink是Consumer的扩展,用于流管道中的多个操作阶段中进行数据的监管

通过额外的方法来管理大小信息 流控等

调用accept前需要调用begin通知数据到来,数据发送完成后需要调用end,再次调用accept前必须再次调用begin 

一个sink有两种状态,初始/激活

开始时是初始状态,begin 激活 ,  end使之回到初始状态,可以重复利用 

accept只能在激活状态使用

 

Sink用于协调相邻的stage之间的数据调用

通过begin end accept方法 以及cancellationRequested短路标志位来控制处理流程,对数据进行管控

https://www.cnblogs.com/noteless/p/9505098.html

Spliterator 

Spliterator 是Java 8中加入的另一个新接口;这个名字代表“可分迭代器”(splitableiterator)。

和 Iterator 一样,Spliterator 也用于遍历数据源中的元素,但它是为了并行执行而设计的。

采用了分治的思想

延迟绑定
你已经看到了 Spliterator 如何让你控制拆分数据结构的策略。

Spliterator 还有最后一个值得注意的功能,就是可以在第一次遍历、第一次拆分或第一次查询估计大小时绑定元素的数据源,而不是在创建时就绑定。

这种情况下,它称为延迟绑定(late-binding)的 Spliterator 。
原文链接:https://blog.csdn.net/ryo1060732496/article/details/88831879

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值