java基础面试题

一、概述 

1、什么是Java

Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。

2、jdk1.5之后的三大版本

Java SE(J2SE,Java 2 Platform Standard Edition,标准版)
Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为Java EE和Java ME提供基础。

Java EE(J2EE,Java 2 Platform Enterprise Edition,企业版)
Java EE 以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web2.0应用程序。2018年2月,Eclipse 宣布正式将 JavaEE 更名为 JakartaEE

Java ME(J2ME,Java 2 Platform Micro Edition,微型版)
Java ME 以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。

3、JVM、JRE和JDK的关系

JVM
Java Virtual Machine是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。

JRE
Java Runtime Environment包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包

如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

JDK
Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等
 

 4、Java语言有哪些特点

简单易学(Java语言的语法与C语言和C++语言很接近)

面向对象(封装,继承,多态)

平台无关性(Java虚拟机实现平台无关性)

支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的)

支持多线程(多线程机制使应用程序在同一时间并行执行多项任)

健壮性(Java语言的强类型机制、异常处理、垃圾的自动收集等)

安全性

5、什么是字节码?采用字节码的最大好处是什么
字节码:Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。

采用字节码的好处:

Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。

Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm---->jvm中解释器----->机器可执行的二进制机器码---->程序运行。

6、Java应用程序与小程序之间有那些差别?

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

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

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

9、Oracle JDK 和 OpenJDK 的对比

  • Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;
  • OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;
  • Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;
  • 在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;
  • Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;
  • Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。
     

二、基础语法

数据类型

1、Java有哪些数据类型

定义:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间。

分类

基本数据类型
   数值型
         整数类型(byte,short,int,long)
         浮点类型(float,double)
  字符型(char)
  布尔型(boolean)
引用数据类型
   类(class)
   接口(interface)
   数组([])

 2、switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上
在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
3、计算

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

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

short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗
对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。

而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。

编码

4、Java语言采用何种编码方案?有何特点?

Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。

注释

5、什么Java注释

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

分类

  • 单行注释
    格式: // 注释文字
  • 多行注释
    格式: /* 注释文字 */
  • 文档注释
    格式:/** 注释文字 */

访问修饰符

访问修饰符 public,private,protected,以及不写(默认)时的区别
定义:Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

分类

private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
public : 对所有类可见。使用对象:类、接口、变量、方法

 运算符

java中&叫做按位与,&&叫做短路与,它们的区别是:

& 既是位运算符又是逻辑运算符,&的两侧可以是int,也可以是boolean表达式,当&两侧是int时,要先把运算符两侧的数转化为二进制数再进行运算,而短路与(&&)的两侧要求必须是布尔表达式。举例如下:

12&5 的值是多少?答:12转成二进制数是1100(前四位省略了),5转成二进制数是0101,则运算后的结果为0100即4 这是两侧为数值时;

关键字

1. Java 有没有 goto

goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。

2. final 有什么用?

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

被final修饰的类不可以被继承
被final修饰的方法不可以被重写
被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的

3. final finally finalize区别

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

4. this关键字的用法

this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。

this的用法在java中大体可以分为2种:

①. 普通的直接引用,this相当于是指向当前对象本身。

②. 形参与成员名字重名,用this来区分:

public Person(String name, int age) {
    this.name = name;
    this.age = age;
}

5.super关键字的用法

super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

super也有三种用法:

1.普通的直接引用

与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。

2.子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分
 

class Person{
    protected String name;
 
    public Person(String name) {
        this.name = name;
    }
 
}
 
class Student extends Person{
    private String name;
 
    public Student(String name, String name1) {
        super(name);
        this.name = name1;
    }
 
    public void getInfo(){
        System.out.println(this.name);      //Child
        System.out.println(super.name);     //Father
    }
 
}

public class Test {
    public static void main(String[] args) {
       Student s1 = new Student("Father","Child");
       s1.getInfo();
 
    }
}

3.引用父类构造函数

  • super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
  • this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

6.this与super的区别

  • super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
  • this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
  • super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
  • super()和this()均需放在构造方法内第一行。
  • 尽管可以用this调用一个构造器,但却不能调用两个。
  • this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
  • this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
  • 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字

7. static的独特之处

  • 被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。
  • 在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。
  • static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!
  • 被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

8. static应用场景

因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。

因此比较常见的static应用场景有:

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

9. static注意事项

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

流程控制语句

1.在 Java 中,如何跳出当前的多重嵌套循环

在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。例如:

public static void main(String[] args) {
    ok:
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            System.out.println("i=" + i + ",j=" + j);
            if (j == 5) {
                break ok;
            }
 
        }
    }
}

三、面向对象

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

面向过程:

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展

面向对象:

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护

缺点:性能比面向过程低

2、面向对象特性

面向对象三大特性

面向对象有哪些特性,下面的就是。面向对象三大特性,除抽象外都是。

抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

封装

封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。

继承

继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

关于继承如下 3 点请记住:

  1. 子类拥有父类非 private 的属性和方法。
  2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
  3. 子类可以用自己的方式实现父类的方法。(以后介绍)。

多态性

多态性父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。

多态分为两种:编译时的多态性、运行时的多态性

方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。

什么是多态机制?Java语言是如何实现多态的?

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

多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编译之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。

java中的重载与重写的区别:1、重载发生在本类,重写发生在父类与子类之间;2、重载的方法名必须相同,重写的方法名相同且返回值类型必须相同;3、重载的参数列表不同,重写的参数列表必须相同。

多态的实现

Java实现多态有三个必要条件:继承、重写、向上转型。

继承:在多态中必须存在有继承关系的子类和父类。

重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。

对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。

3、类与接口

1. 抽象类和接口的对比

抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。

从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

相同点

接口和抽象类都不能实例化
都位于继承的顶端,用于被其他实现或继承
都包含抽象方法,其子类都必须覆写这些抽象方法

不同点

2. 普通类和抽象类有哪些区别?

普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。

3. 抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类

4. 创建一个对象用什么关键字?对象实例与对象引用有何不同?

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

4、变量与方法

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

变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存中的一小块区域

成员变量:方法外部,类内部定义的变量

局部变量:类的方法中的变量。

成员变量和局部变量的区别

作用域

成员变量:针对整个类有效。
局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)

存储位置

成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结束后,就自动释放。

生命周期

成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:当方法调用完,或者语句结束后,就自动释放。

初始值

成员变量:有默认初始值。

局部变量:没有默认初始值,使用前必须赋值。

使用原则

在使用变量时需要遵循的原则为:就近原则
首先在局部范围找,有就使用;接着在成员位置找。

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

名字与类名相同;

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

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

3.静态变量与普通变量区别

static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化。

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

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

在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制

5、内部类

1. 什么是内部类?

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

2. 内部类的分类有哪些

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

3. 内部类的优点

我们为什么要使用内部类呢?因为它有以下优点:

  • 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
  • 内部类不为同一包的其他类所见,具有很好的封装性;
  • 内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
  • 匿名内部类可以很方便的定义回调。

6、重写与重载

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

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

重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分

重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为private则子类中就不是重写。

7、对象相等判断

7..1、== 和 equals 的区别是什么

首先的区别是,equals 是方法,而 == 是操作符;

其次,基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址;

最后是,对于引用类型的变量来说(例如 String 类)才有 equals 方法,

它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

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

情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们

public class test1 {
    public static void main(String[] args) {
        String a = new String("ab"); // a 为一个引用
        String b = new String("ab"); // b为另一个引用,对象的内容一样
        String aa = "ab"; // 放在常量池中
        String bb = "ab"; // 从常量池中查找
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false,非同一对象
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }
    }
}

参考:equals 和 == 的区别 - 小蚊子大人KN - 博客园

7.2、hashcode和equals的区别和联系

equals 本质上就是 ==,因为很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

hashcode通俗的来讲就是对象在hash表中有对应的位置,返回值位int类型,主要是为了查找的快捷性。

区别
equals 返回布尔类型,hashcode返回int类型
equals重在比较,hashcode重在返回对象在hash表的位置
默认的hashcode方法返回值永远大于等于0,默认的equals方法实际上就是"=="的比较
联系
重写equals 方法之后,也要重写hashcode方法
equals结果如果是相同,那么hashcode也一定相同,反之hashcode相同但equals不一定相同
实际应用中可以根据情况重写相关代码,减少equals次数,以提升代码效率

7.3、为什么重写了equals也要重写hashcode方法?

比如:有个A类重写了equals方法,但是没有重写hashCode方法,看输出结果,对象a1和对象a2使用equals方法相等,按照上面的hashcode的用法,那么他们两个的hashcode肯定相等,但是这里由于没重写hashcode方法,他们两个hashcode并不一样,所以,我们在重写了equals方法后,尽量也重写了hashcode方法,通过一定的算法,使他们在equals相等时,也会有相同的hashcode值。

8.值传递和引用传递

值传递和引用传递有什么区别?
值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。

引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

9.Java包

9.1 java常用的包有哪些?

  • java.lang:这个是系统的基础类;包括基本Object类、Class类、String类、基本类型的包装类、基本的数学类等等最基本的类。
  • java.io:这里面是所有输入输出有关的类,比如文件操作等;
  • java.net:这里面是与网络有关的类;
  • java.util:这个是系统辅助类,特别是集合类;
  • java.sql:这个是数据库操作的类。

9.2 import java和javax有什么区别

刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来说使用。然而随着时间的推移,javax 逐渐的扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包将是太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准API的一部分。

所以,实际上java和javax没有区别。这都是一个名字。

四、IO流

4.1 什么是IO流?

IO流用来处理不用设备之间的数据传输

这里我们可以拆解出来

I:表示输入(Input读取数据),从硬盘等设备中读取数据到内存中,这个过程称为输入流

O:输出(Output 写数据),程序的内存数据写入到我们的硬盘等设备中,这个过程称为输出流

4.2 IO流分类

第一种:输入流和输出流

第二种:字节流和字符流

字节流,按 8 位传输,以字节为单位输入输出数据;

字符流,按 16 位传输,以字符为单位输入输出数据;

字节流,二进制,可以处理一切文件,包括:纯文本、doc、音频、视频等;
字符流,文本文件,只能处理纯文本。

第三种:节点流和处理流

节点流:可以从向一个特定的IO设备(如磁盘、网络)读/写数据的流。也被称为低级流。
处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能。也称为高级流。

4.3 节点流和处理流的区别和联系

  1. 节点流是底层流/低级流,直接跟数据源连接。
  2. 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入和输出。
  3. 处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连接。

4.4 IO流按操作方式分类和按操作对象分类

Java Io流共涉及40多个类,Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

IO-操作方式分类

按操作对象分类结构图 

 使用参考:(Java笔记)IO流的六类16种流方式_电竞丶小松哥的博客-CSDN博客_java流的方法

4.5 Files的常用方法都有哪些?

Files. exists():检测文件路径是否存在。
Files. createFile():创建文件。
Files. createDirectory():创建文件夹。
Files. delete():删除一个文件或目录。
Files. copy():复制文件。
Files. move():移动文件。
Files. size():查看文件个数。
Files. read():读取文件。
Files. write():写入文件。

4.6 BIO,NIO,AIO 有什么区别?

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。


NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。


AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

4.7 Java序列化

4.7.1序列化与反序列化的定义

4.7.2 序列化的原因

 4.7.3 如何实现序列化

 4.7.4 注意点

五、反射

5.1 什么是反射机制?

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
 

5.2 Java获取Class对象三种方法?

1.通过new对象实现反射机制

2.通过路径实现反射机制

3.通过类名实现反射机制

public class Student {
    private int id;
    String name;
    protected boolean sex;
    public float score;
}
public class Get {
    //获取反射机制三种方式
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一(通过建立对象)
        Student stu = new Student();
        Class classobj1 = stu.getClass();
        System.out.println(classobj1.getName());
        //方式二(所在通过路径-相对路径)
        Class classobj2 = Class.forName("fanshe.Student");
        System.out.println(classobj2.getName());
        //方式三(通过类名)
        Class classobj3 = Student.class;
        System.out.println(classobj3.getName());
    }
}

5.3 反射常用方法

参考:反射常用方法_zheng_chang_wei的博客-CSDN博客_反射常用方法

六、网络编程

七、常用API

7.1 String相关

7.1.1 字符型常量和字符串常量的区别

1. 形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的 若干个字符

2. 含义上: 字符常量相当于一个整形值( ASCII 值),可以参加表达式运算,字符串常量代表一个地址值(该字符串在内存中存放位置)

3. 占内存大小 字符常量只占2个字节 字符串常量占若干个字节(至少一个 字符结束标志) (注意: char在Java中占两个字节)

7.1.2 什么是字符串常量池?

字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。

7.1.3 String有哪些特性

  • 常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。

  • final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。

7.1.5 String str="i"与 String str=new String(“i”)一样吗?

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

String str1 = "hello"; //str1指向静态区
String str2 = new String("hello");  //str2指向堆上的对象
String str3 = "hello";
String str4 = new String("hello");
System.out.println(str1.equals(str2)); //true
System.out.println(str2.equals(str4)); //true
System.out.println(str1 == str3); //true
System.out.println(str1 == str2); //false
System.out.println(str2 == str4); //false
System.out.println(str2 == "hello"); //false
str2 = str1;
System.out.println(str2 == "hello"); //true

7.1.6 如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba

7.1.7 数组有没有 length()方法?String 有没有 length()方法

数组没有 length()方法 ,有 length 的属性。String 有 length()方法。JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

7.1.8 String 类的常用方法都有那些?

  • length():返回字符串长度。
  • substring():截取字符串
  • equals():字符串比较。
  • split():分割字符串,返回一个分割后的字符串数组
  • replace():字符串替换。
  • indexOf():返回指定字符的索引。
  • charAt():返回指定索引处的字符。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。

7.1.9 String和StringBuffer、StringBuilder的区别是什么?

可变性

String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。
线程安全性

String中的对象是不可变的,也就可以理解为常量,线程安全。

StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

对于三者使用的总结

如果要操作少量的数据用 = String

单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

7.2 包装类

7.2.1  自动装箱与拆箱

装箱:将基本类型用它们对应的引用类型包装起来;

拆箱:将包装类型转换为基本数据类型;

7.2.2 为什么有基本类型还要有包装类型?

首先,基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型(如我们在使用集合类型 Collection 时就一定要使用包装类型而非基本类型),它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作

另外,集合类(ArrayList,HashMap等)里面保存的必须是 Object 类型的对象,无法保存基本类型。

7.2.3 那只有包装类型不就可以了?

我们知道 Java 中,new 一个对象会存储在堆里,我们通过栈中的引用来使用这些对象。由于基本数据类型很常用,如果我们用 new 将其存储在堆里效率明显降低。

7.2.4 基本类型和包装类型的异同

在 Java 中,一切皆对象,但八大基本类型却不是对象。
声明方式的不同:基本类型无需通过 new 关键字来创建,而封装类型需 new 关键字。
存储方式及位置的不同,基本类型是直接把存储变量的值保存在栈中能高效的存取,封装类型需要通过引用指向实例,具体的实例保存在堆中。
初始值的不同,封装类型的初始值为 null,基本类型的初始值视具体的类型而定,比如 int 类型的初始值为 0,boolean 类型为 false。
使用方式的不同,比如与集合类合作使用时只能使用包装类型。
什么时候该用包装类,什么时候用基本类型,看基本的业务来定。这个字段允不允许 null 值,如果允许 null 值,则必需用封装类,否则值类型就可以了。用到比如泛型和反射调用函数,就需要用包装类。

7.2.5 Integer a= 127 与 Integer b = 127相等吗

相等

对于对象引用类型:==比较的是对象的内存地址。
对于基本数据类型:==比较的是值。

而当我们用Integer表示int类型的时候,就会调用静态方法valueOf

下列这段代码中明确的写着Integer的取值范围,是-128~127;所以当超过这个范围的时候就会重新在堆内存当中new一个新的Integer对象。这个时候内存地址的值不再相同所以就会返回false


        Integer a = new Integer(3);
        Integer b = 3;                  
        int c = 3;
        System.out.println(a == b);    
        System.out.println(a == c);     

答案:false  true

解答:第一个是两个引用之间的比较,他们没有引用同一对象,所以为false

           第二个是a会自动拆箱成int类型,再去和c比较,所以本质其实是基本类型的比较

 
        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
        System.out.println(f1 == f2);
        System.out.println(f3 == f4);
 

答案:true false

解答:很多人可能觉得会都是false, 因为这四个都是Integer对象的引用,所以 == 比较的都不是值,而是引用

当我们给一个Integer 对象赋一个Int值的时候,调用的是Integer 的valueOf 方法,所以去看看Integer里面的源码就会发现,其实-128 - 127之间的数字不会new新的对象,而是直接类加载的时候就直接缓存了对应的对象,需要时直接取的缓存里面的。

八、常用工具类库

九、单元测试

十、日志

参考:

Java基础知识面试题(2020最新版)_ThinkWon的博客-CSDN博客_java基础面试题

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值