1、JVM

java JVM是运行Java字节码的虚拟机。jvm有针对不同系统得特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们会给出相同的结果。

2、字节码

在Java中,jvm可以理解的代码就叫做字节码(即扩展名为.class的文件),只面向虚拟机。无需重新编译就可在不同的操作系统上运行。

3、过程

.java file --> (by javac compile in JDK)  .class file  --> (by JVM) machine can do 
Java是编译与解释共存的语言,JIT编译器,Java 9引入了新的编译模式AOT(ahead of time compilation),JDK支持分层编译和AOT协作使用,但是AOT编译器的编译质量是比不上JIT编译器的。

4、JDK

java development kit,功能齐全的Java sdk。它拥有jre(Java运行时环境)所拥有的一切,包括javac和工具。它能够创建和编译程序。

5、Orale JDK & OpenJDK 的对比

对于Java 7,没什么关键的地方。OpenJDK项目主要基于Sun捐赠的HotSpot源代码。此外,OpenJDK被选为Java 7的参考实现,由Oracle工程师维护。关于JVM,JDK,JRE和OpenJDK之间的区别,Oracle博客帖子在2012年有一个更详细的:
区别:  
    非常接近,非常接近 - 我们的Oracle JDK版本构建过程基于OpenJDK 7构建,只添加了几个部分,例如部署代码,其中包括Oracle的Java插件和Java WebStart的实现,以及一些封闭的源代码派对组件,如图形光栅化器,一些开源的第三方组件,如Rhino,以及一些零碎的东西,如附加文档或第三方字体。展望未来,我们的目的是开源Oracle JDK的所有部分,除了我们考虑商业功能的部分。
总结:  
    1、Oracle JDK每三年发布一次,OpenJDK每三个月发布一次;
    2、openjdk是一个参考模型并且是完全开源的,oracle JDK是openJDK的一个实现,并不完全开源;
    3、Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;   
    4、在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;  
    5、Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;
    6、Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。

6、Java与C++的区别?

1、都是面向对象的语言,都是支持封装、继承、多态    
2、Java不提供指针来直接访问内存,程序内存更安全  
3、Java的类是单继承的,C++支持多继承;但Java接口可以多继承  
4、Java有自动内存管理机制,不需要程序员手动释放无用内存  

7、什么是Java程序的主类,应用程序和小程序的主类有何不同?

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

8、Java Application & mirApplication ?

简单说应用程序是从主线程启动(main()方法),applet小程序没有main方法,主要是嵌在浏览器页面上运行(调用init线程或者run来启动),嵌入浏览器这点跟flash的小游戏类似。

9、字符型常量和字符串常量的区别?

1、形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的若干个字符
2、含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
3、占内存大小 字符常量只占2个字节; 字符串常量占若干个字节(至少一个字符结束标志) (注意: char在Java中占两个字节)

10、构造器constructor是否可被override?

父类的私有属性和构造方法不能被继承,所以constructor也就不能被重写,但可以overload(重载),所以你可以看到一个类中有多个构造函数的情况。

11、重写和重载的区别?

1、重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符号可以不同,发生在编译时。
2、发生在父类和子类间,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。

12、Java面对对象编程三大特性:封装、继承、多态

  • 1、封装 把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法
  • 2、继承 使用已经存在的类为基础建立新类的技术,新类可以增加新的数据或新的功能,可以用父类的功能,但不能选择性地继承父类。通过使用继承我们可以非常方面地复用以前的代码。
    ⚠️ 关于继承如下 3 点请记住:
    1、子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
    2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
    3、子类可以用自己的方式实现父类的方法。(以后介绍)
  • 3、多态
    所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而在程序运行时才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
    ⚠️ 实现多态的形式:继承(多个子类对同一个方法的重写),和接口(实现接口并覆盖接口中同一方法)

13、String StringBuilder StringBuffer区别?为啥String是不可变的?

  • 1、不可变性 String类中使用final关键字修饰字符数组来保存字符串,private final char value[],所以String对象是不可变的。StringBuilder、StringBuffer都继承自AbstractStringBuilder类,在AbstractBuilder中也是使用字符数组保存字符串char[]value但是没有用final关键字修饰,所以是可变的。
  • 2、StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的。
  • 3、线程安全性
    String中的对象是不可变的,也可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
  • 4、性能
    每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
  • 5、总结
    1、操作少量的数据:使用String
    2、单线程操作字符串缓冲区下操作大量数据:使用 StringBuilder
    3、多线程操作字符缓冲区下操作大量数据:适用StringBuffer

14、自动装箱与拆箱

  • 1、装箱
    将基本类型它们对应的引用类型包装起来;
  • 2、拆箱
    将包装类型转换为基本数据类型;

15、在一个静态方法中调用一个非静态成员是非法的。静态方法可以不通过对象来调用,因此在静态方法中,不能调用其他非静态变量,也不可以访问非静态变量成员。

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

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

###17、import java 和import javax的区别?

  • 1、刚开始时,JavaAPI所需要的包是Java开头的包,javax当时只是扩展API包来使用,编by the time,javax扩展成为JavaAPi的组成部分。
  • 2、但是将,扩展从 javax 包移动到 java 包确实太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准API的一部分。
  • 所以,实际上java和javax没有区别。这都是一个名字

18、接口和抽象类的区别?

  • 1、接口的方法默认是public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),而抽象类可以有非抽象的方法。
  • 2、接口中除了static、final变量,不能有其他变量,而抽象类中则不一定。
  • 3、一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过extends关键字扩展多个接口。
  • 4、接口方法默认修饰符是public,抽象方法可以有public、protected和default这些修饰符(抽象方法就是为了被重写所以不能使用private关键字修饰!)。
  • 5、从设计层面来说,抽象是对类的抽象,是一种模版设计,而接口是对行为的抽象,是一种行为的规范。
  • 6、在jdk8中,接口也可以定义静态方法,可以直接接口名调用。实现类和实现是不可以调用的。如果同时实现两个接口,接口中定义一样的默认方法,则必须重写,否则会报错。

19、成员变量与局部变量的区别?

  • 1、从语法形式上看: 成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
  • 2、从变量在内存中的存储方式来看: 如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。
  • 3、从变量在内存中的生寸时间来看: 成员变量是对象的一部分,随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
  • 4、成员变量如果没有被赋初值:则会自动以类型的默认值而赋值(一种情况例外被 final 修饰的成员变量也必须显示地赋值),而局部变量则不会自动赋值。

20、什么是方法的返回值?返回值在类的方法里的作用是什么?

方法的返回值是🈯我们获取到某个方法体中代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收结果,使得它可以用于其他的操作。

21、一个类的构造方法的作用?

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

22、构造方法有哪些特性?

  • 1、名字与类名相同
  • 2、没有返回值,但不能用void声明构造函数
  • 3、生成类的对象时自动执行,无需调用。

23、静态方法和实例方法有何不同?

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

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

24、对象的相等与指向它们的引用相等,两者有什么不同?

  • 对象的相等,比的是内存中存放的内容是否相等。
  • 引用的相等,比的是它们指向的内存地址是否相等。

25、在调用子类构造方法之前会先调用父类的没有参数的构造方法,目地是?

帮助子类做初始化工作

26、(重要)== 与 equals

  • 1、== 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
  • 2、equals 它的作用也是判断两个对象是否相等。但它一般有两种使用情况: 情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。 情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

27、(重要)hashCode与equals

  • 1、扩展链接https://www.cnblogs.com/skywang12345/p/3324958.html
  • 2、hashCode()介绍 该函数作用是获取哈希码,它实际返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()定义在JDK的Object.java中,这意味着Java中的任何类都包含有hashCode()函数。
  • 3、为什么要有hashCode hashCode()在散列表中才有用,其他情况下,没有用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
  • 4、hashCode()与equals()的相关规定
    • 1、如果两个对象相等,则hashCode一定也是相同的
    • 2、两个对象相等,对两个对象分别调用equals方法,都返回true
    • 3、两个对象有相同的hashCode值,它们也不一定是相等的
    • 4、因此,equals方法被覆盖过,则hashCode方法也必须被覆盖
    • 5、hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

28、为什么Java中只有值传递?

###29、简述线程、程序、进程的基本概念。以及他们之间关系是什么?

  • 1、线程 线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
  • 2、程序 程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
  • 3、进程 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。

30、线程有哪些基本状态?

  • 1、Java线程在运行的生命周期中的指定时刻只可能处于以下6种不同状态的其中一个状态
    • 1、new,初始状态,线程被构建但是还没有调用start()方法来比较两个对象的内容是否相等;
    • 2、Runnable,运行状态,Java线程将操作系统中的就绪和运行两种状态笼统地称作“运行中”
    • 3、blocked,阻塞状态,表示线程阻塞于锁;
    • 4、Waiting,等待状态,表示线程进入等待状态,
    • 5、Time_Waiting超时等待状态,该状态不同于Waiting,它是可以在指定的时间自行返回的
    • 6、Terminated,终止状态,表示当前线程已经执行完毕。
  • 2、线程在生命周期中并不是固定处于某一个状态而是随着代码的执行在不同的状态之间切换。
  • 3、 线程创建之后它将处于 NEW(新建) 状态,调用 start() 方法后开始运行,线程这时候处于 READY(可运行) 状态。可运行状态的线程获得了 cpu 时间片(timeslice)后就处于 RUNNING(运行) 状态。 当线程执行 wait()方法之后,线程进入 WAITING(等待)状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。线程在执行 Runnable 的run()方法之后将会进入到 TERMINATED(终止) 状态。

31、关于final关键字的一些总结

final主要用在三个地方:变量、方法、类

  • 1、对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
  • 2、当用final修饰一个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为final方法。
  • 3、使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。类中所有的private方法都隐式地指定为final。

32、Java中的异常处理

  • 1、种类 exception(异常)
    error(错误)
  • 2、异常能被程序本身处理,error是无法处理的。
  • 3、扩展链接https://github.com/Snailclimb/JavaGuide/issues/190

33、Java序列化中如果有些字段不能进行序列化,怎么办?

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

34、获取用键盘输入常用的两种方法?

  • 1、通过Scanner Scanner input = new Scanner(System.in);
    String s = input.nextLine();
    input.close()
  • 2、通过BufferedReader BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    String s = input.readLine();

35、Java中IO流分为几种?BIO,NIO,AIO的区别?

  • 1、种类 按照流的流向,输入流和输出流
    按照操作单元划分,字节流和字符流
    角色划分,节点流和处理流
  • 2、Java Io流共涉及到40多各类,但都是从下面4各抽象类中派生出来的
    InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
    OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
  • 3、BIO,NIO,AIO的区别?
    • BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

    • NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发

    • AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

36、常见关键字总结:static、final、this、super

37、Collections工具类和Arrays工具类常见方法总结

本文系个人总结的Java基础面试题!仅作为个人知识库使用!