Java基础-中级-高级面试题汇(一)
第一部分: Java基础面试题汇总
1.面向对象和面向过程的区别?
面向对象和面向过程是两种不同的编程思想。
面向对象是一种以对象为中心的编程思想,将数据和处理数据的方法封装在一起,形成一个类。程序通过创建对象来调用类中的方法,实现对数据的操作。面向对象的编程思想强调抽象、封装、继承和多态。
面向过程则是一种以过程为中心的编程思想,将问题分解为一系列的步骤,每个步骤对应一个函数,函数之间通过参数传递数据,实现对数据的操作。面向过程的编程思想强调程序的结构化和流程控制。
//是分析解决问题的步骤,然后用函数把这些步骤一步一步地实现,然后在使用的 时候一一调用则可。性能较高,所以单片机、嵌入式开发等一般采用面向过程开发。
相比之下,面向对象更加灵活和易于维护,因为它将数据和方法封装在一起,避免了数据的直接访问和修改,同时也方便了代码的复用和扩展。而面向过程则更加直观和简单,适用于一些简单的问题。
2.Java 语言有哪些特点?
1. 面向对象:Java 是一种面向对象的编程语言,所有的代码都是以对象的方式来组织和实现的。
2. 简单易学:Java 语言的语法和结构都比较简单,易于学习和使用。
3. 平台无关性:Java 语言可以在不同的操作系统和硬件平台上运行,只需要安装相应的 Java 虚拟机即可。
4. 安全性:Java 语言的安全性非常高,可以防止一些常见的安全漏洞,如缓冲区溢出、空指针引用等。
5. 高性能:Java 语言的性能比较高,尤其是在多线程和网络编程方面表现突出。
6. 可移植性:Java 语言的程序可以很方便地移植到不同的平台上,只需要重新编译一下即可。
7. 开放性:Java 语言是一种开放的标准,任何人都可以使用和开发 Java 应用程序。
8. 多线程支持:Java 语言提供了丰富的多线程支持,可以方便地实现多线程编程。
9. 异常处理机制:Java 语言提供了完善的异常处理机制,可以很好地处理程序中出现的异常情况。
10. 动态性:Java 语言具有很强的动态性,可以在运行时动态加载和执行代码。
3.关于 JVM JDK 和 JRE 最详细通俗的解答
JVM、JDK和JRE都是Java开发中常见的概念。它们之间的关系如下:
JVM(Java Virtual Machine):Java虚拟机,是Java程序的运行环境。它能够解释Java字节码并将其转换为机器码,使得Java程序能够在不同的平台上运行。
JDK(Java Development Kit):Java开发工具包,包含了JVM、Java编译器(javac)、Java文档生成器(javadoc)等工具和类库。它是Java开发的基础,用于编写、编译和运行Java程序。
JRE(Java Runtime Environment):Java运行时环境,包含了JVM和Java类库,用于运行Java程序。相比JDK,JRE不包含Java编译器和其他开发工具。
简单来说,JDK是Java开发的必备工具,JRE是Java程序运行的必备环境,而JVM则是Java程序运行的核心。
总结一下:
JVM:Java虚拟机,运行Java程序的环境。
JDK:Java开发工具包,包含了JVM和其他开发工具和类库。
JRE:Java运行时环境,包含了JVM和Java类库,用于运行Java程序。
4.Java 和 C++的区别?
Java 和 C++ 是两种不同的编程语言,它们有以下区别:
1. 编译和解释:C++ 是一种编译语言,需要将源代码编译成可执行文件。而 Java 是一种解释语言,需要将源代码编译成字节码,然后在运行时通过 Java 虚拟机解释执行。
2. 内存管理:C++ 是一种手动管理内存的语言,程序员需要自己分配和释放内存。而 Java 有自动内存管理机制,程序员不需要手动管理内存。
3. 平台依赖性:C++ 是一种平台相关的语言,程序需要编译成特定平台的可执行文件。而 Java 是一种平台无关的语言,可以在任何支持 Java 虚拟机的平台上运行。
4. 多线程支持:Java 内置了多线程支持,可以方便地实现多线程编程。而 C++ 需要使用操作系统提供的多线程库来实现多线程编程。
5. 异常处理:Java 内置了异常处理机制,程序员可以方便地处理异常。而 C++ 的异常处理需要程序员自己实现。
6. 对象模型:Java 是一种基于对象的语言,所有数据类型都是对象。而 C++ 既支持面向对象编程,也支持过程式编程。
5.什么是 Java 程序的主类?应用程序和小程序的主类有何不同?
Java 程序的主类是指程序入口,类的名字和文件名一致,并且包含main函数的类,叫做主类。在执行 Java 程序时,JVM 会自动寻找并执行主类中的 main() 方法。
应用程序的主类通常是一个独立的 Java 程序,可以通过命令行或者双击图标等方式启动,它通常包含一个 GUI 界面,提供给用户交互。
小程序的主类通常是一个微信小程序或者其他类似的轻量级应用程序,它们运行在特定的平台上,如微信、支付宝等,通常不需要像应用程序那样提供 GUI 界面,而是通过特定的 API 和平台进行交互。
6.Java 应用程序与小程序之间有哪些差别?
Java 应用程序与小程序之间的主要差别如下:
1. 运行环境:Java 应用程序需要在安装了 Java 运行环境(JRE)的计算机上运行,而小程序则是在微信或其他小程序平台上运行。
2. 功能:Java 应用程序通常具有更复杂的功能,可以进行更多的计算和处理,而小程序则主要用于简单的交互和展示。
3. 开发难度:Java 应用程序的开发难度较高,需要掌握 Java 编程语言和相关的开发工具,而小程序则使用的是类似于 HTML 和 CSS 的开发语言,相对较易上手。
4. 发布和分发:Java 应用程序需要通过安装包或者网络下载等方式进行发布和分发,而小程序则直接在小程序平台上进行发布和分发。
5. 用户体验:小程序可以提供更快速、更轻量级的用户体验,而 Java 应用程序则需要较高的计算资源和较长的加载时间。
7.字符型常量和字符串常量的区别
字符型常量是由单个字符组成的常量,用单引号括起来,例如 'a'、'1'、'+' 等。而字符串常量是由多个字符组成的常量,用双引号括起来,例如 "hello"、"123"、"+" 等。字符型常量只能表示一个字符,而字符串常量可以表示多个字符。在Java中,字符型常量是基本数据类型char,而字符串常量是引用数据类型String。
8.构造器 Constructor 是否可被 override
构造器 Constructor 不能被 override,因为它是一个特殊的方法,用于创建对象并初始化其成员变量。在子类中,可以使用 super() 调用父类的构造器来初始化父类的成员变量,但不能重写父类的构造器。如果子类没有显式地调用父类的构造器,则会默认调用父类的无参构造器。
9.重载和重写的区别?
重载(Overloading)和重写(Overriding)是Java中的两个重要概念。
重载指的是在一个类中定义多个同名的方法,但是这些方法的参数列表不同,可以有不同的参数类型、参数个数、参数顺序等。重载的方法在调用时会根据传入的参数类型和个数来匹配对应的方法。
重写指的是在子类中重新定义父类中已有的方法,方法名、参数列表和返回值类型必须与父类中的方法相同。重写的方法在调用时会优先调用子类中的方法。
总结来说,重载是在一个类中定义多个同名方法,参数列表不同,而重写是在子类中重新定义父类中已有的方法。重载是编译时多态性,重写是运行时多态性。
如果在编译时能够确定执行多态方法称为编译时多态,否则称为运行时多态。
10.Java 面向对象编程三大特性: 封装 继承 多态
封装:将数据和方法封装在一个类中,对外部隐藏实现细节,只暴露必要的接口,提高代码的安全性和可维护性。
继承:子类可以继承父类的属性和方法,可以重写父类的方法,实现代码的复用和扩展。
多态:同一种类型的对象,在不同的情况下可以表现出不同的行为,提高代码的灵活性和可扩展性。多态实现的方式包括方法重载、方法重写和接口实现。
11.String StringBuffer 和 StringBuilder 的区别是什么?String 为什么是不可变的?
String、StringBuffer 和 StringBuilder 都是用来存储字符串的类,但是它们之间有以下不同:
1. String 是不可变的,而 StringBuffer 和 StringBuilder 是可变的。这意味着 String 对象一旦创建,就不能修改它的值,而 StringBuffer 和 StringBuilder 对象可以修改。
2. String 对象在每次修改时都会创建一个新的对象,而 StringBuffer 和 StringBuilder 对象则会在原对象上修改。
3. StringBuffer 和 StringBuilder 的效率比 String 更高,因为它们不需要每次修改都创建一个新的对象。
String 是不可变的主要原因是为了安全性和线程安全。由于 String 对象是不可变的,所以它们可以被安全地共享,不会被意外修改。此外,在多线程环境下,String 对象的不可变性可以避免线程安全问题。如果多个线程同时修改一个可变的对象,可能会导致数据不一致或其他问题。
答案2:
String 是不可变的,因为它的值在创建后不能被修改。每次对 String 进行修改时,都会创建一个新的 String 对象,而原始的 String 对象则保持不变。这种不可变性带来了一些好处,如线程安全、安全性和缓存等。
StringBuffer 和 StringBuilder 都是可变的字符串类,它们的主要区别是线程安全性和性能。StringBuffer 是线程安全的,因为它的方法都是同步的,而 StringBuilder 则不是线程安全的,因为它的方法没有同步。因此,在多线程环境下,应该使用 StringBuffer,而在单线程环境下,建议使用 StringBuilder,因为它的性能更好。
12.自动装箱与拆箱
Java中的自动装箱和拆箱是指Java编译器在编译时自动将基本数据类型和其对应的包装类之间进行转换的过程。
自动装箱:将基本数据类型转换为对应的包装类对象。例如,将int类型的值自动转换为Integer类型的对象。
自动拆箱:将包装类对象转换为基本数据类型。例如,将Integer类型的对象自动转换为int类型的值。
自动装箱和拆箱的好处在于,它们使得编码变得更加简单和方便。在使用集合类或泛型时,自动装箱和拆箱可以避免手动进行类型转换的麻烦,提高了代码的可读性和可维护性。
需要注意的是,自动装箱和拆箱操作可能会影响程序的性能。因为它们需要创建对象和进行类型转换,所以在需要高性能的场景下,应该尽量避免频繁地进行自动装箱和拆箱操作。
13.在一个静态方法内调用一个非静态成员为什么是非法的?
在一个静态方法中调用非静态成员是非法的,因为静态方法是属于类的,而非静态成员是属于对象的。在静态方法中无法访问对象的成员,因为没有对象实例化。如果要在静态方法中访问非静态成员,需要先创建对象实例,然后通过对象实例来访问非静态成员。
14.在 Java 中定义一个不做事且没有参数的构造方法的作用?
1、java中无参数构造方法的存在是因为在创建子类的时候实例化对象报错。
2、创建子类的对象实例的时候,必先调用父类的无参数的构造函数(默认构造函数),假如父类有带参数的构造函数,那么系统将不会给它创建无参数的构造函数,这时,子类在实例化的时候,因为找不到父类的默认构造函数,编译器将会报错,但如果在子类的构造函数中指定用父类的带参数的构造函数的时候,或者在父类中加一个无参数的构造函数,就不会报错。
15.import java 和 javax 有什么区别?
刚开始的时候JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来说使用。然而随着时间的推移,javax 逐渐的扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准API的一部分。
所以,实际上java和javax没有区别。这都是一个名字。
16.接口和抽象类的区别是什么?
1.定义:抽象类是一个类,可以有普通方法和抽象方法,其中抽象方法必须被子类实现;接口是一组抽象方法的集合,所有方法都是抽象方法,且没有具体实现。
2.实现:子类只能继承一个抽象类,但可以实现多个接口。
3.构造函数:抽象类可以有构造函数,接口没有构造函数。
4.变量:抽象类可以有变量,接口只能定义常量。
5.访问控制:抽象类中的方法可以是public、protected和default访问控制,而接口中的方法默认是public。
6.默认实现:抽象类可以有普通方法的默认实现,而接口中所有的方法都没有默认实现。
7.继承:子类继承抽象类时必须实现其中的抽象方法,否则该子类也必须是抽象类;子类实现接口时必须实现其中的所有方法。
总之,抽象类是对类抽象,接口是对行为抽象。如果一个类具有一些共同的属性和行为,那么可以将这些共同的属性和行为放到抽象类中,让子类继承并实现其中的抽象方法。如果一个类只是具有一些共同的行为,那么可以将这些共同的行为定义到接口中,让实现该接口的类来实现其中的方法。
17.成员变量与局部变量的区别有哪些?
1. 作用域不同:成员变量的作用域是整个类,而局部变量的作用域只在定义它的方法或语句块内部。
2. 生命周期不同:成员变量的生命周期与对象的生命周期相同,而局部变量的生命周期只在定义它的方法或语句块执行期间存在。
3. 默认值不同:成员变量有默认值,而局部变量没有默认值,必须先进行初始化才能使用。
4. 访问修饰符不同:成员变量可以使用访问修饰符进行限制访问,而局部变量不能使用访问修饰符。
5. 存储位置不同:成员变量存储在对象的堆内存中,而局部变量存储在栈内存中。
6. 内存占用不同:成员变量占用的内存空间与对象的个数有关,而局部变量占用的内存空间与方法的调用次数有关。
18.创建一个对象用什么运算符?对象实体与对象引用有何不同?
创建一个对象可以使用 new 关键字来实例化一个类。通过 new 运算符,我们可以在内存中分配空间,并调用类的构造方法来初始化对象。
对象实体和对象引用是两个不同的概念:
• 对象实体:指的是在内存中真正存在的对象,它占据一定的内存空间,并保存了对象的属性值。
• 对象引用:指的是对对象的引用或者说指针,它是一个变量,用于存储对象在内存中的地址。通过对象引用,我们可以访问和操作对象的属性和方法。
简单来说,对象实体是具体的对象,而对象引用是指向对象实体的指针。
举个例子来说明:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("Hello, my name is " + name);
}
}
public class Main {
public static void main(String[] args) {
// 创建对象实体并赋值给对象引用p1
Person p1 = new Person("Alice");
// 创建对象实体并赋值给对象引用p2
Person p2 = new Person("Bob");
// 调用对象引用p1的方法
p1.sayHello(); // 输出:Hello, my name is Alice
// 调用对象引用p2的方法
p2.sayHello(); // 输出:Hello, my name is Bob
}
}
在上面的例子中,通过 new 关键字创建了两个 Person 对象实体,并分别赋值给 p1 和 p2 这两个对象引用。通过对象引用,我们可以调用对象的方法 sayHello()来输出不同的结果。
答案2
Java中使用new运算符来创建一个对象。
对象实体是在内存中分配的一块空间,用于存储对象的数据。而对象引用是一个变量,用于指向对象实体所在的内存地址。对象实体和对象引用的区别在于,对象实体是实际存在的物理实体,而对象引用只是一个指向该实体的标识符。可以有多个对象引用指向同一个对象实体,但每个对象引用都是唯一的。
19.什么是方法的返回值?返回值在类的方法里的作用是什么?
方法的返回值是指方法执行完毕后返回给调用者的值。返回值可以是任何数据类型,包括基本数据类型和对象类型。
返回值在类的方法里的作用是让方法能够向调用者返回结果。通过返回值,调用者可以得到方法执行后的结果,然后根据结果进行下一步的操作。例如,一个计算两个数之和的方法,可以返回计算结果,让调用者使用这个结果进行其他操作。另外,返回值也可以用来控制程序的流程,例如,一个方法返回一个布尔值,可以根据返回值的不同来执行不同的代码块。
20.一个类的构造方法的作用是什么 若一个类没有声明构造方法,该程序能正确执行吗 ?为什么?
一个类的构造方法的作用是用于创建该类的对象并初始化对象的属性。如果一个类没有声明构造方法,则编译器会默认生成一个无参构造方法。因此,程序能够正确执行。
如果在类中没有定义任何构造方法,编译器会自动生成一个默认的无参构造方法。当创建该类的对象时,会调用该默认构造方法来完成对象的初始化。如果该类中定义了其他构造方法,但没有定义无参构造方法,则在创建对象时,如果没有显式地调用其他构造方法,编译器会报错。因此,为了保证程序的正确性,建议在类中定义一个无参构造方法。
21.构造方法有哪些特性?
1. 构造方法与类名相同,没有返回类型,也不需要显式调用。
2. 构造方法用于创建对象时初始化对象的数据成员。
3. 构造方法可以有多个重载形式,根据传入的参数类型和个数不同来区分。
4. 如果没有定义任何构造方法,Java会自动提供一个默认构造方法,其没有参数,也没有任何操作。
5. 如果定义了一个或多个构造方法,则默认构造方法不再提供。
6. 构造方法可以访问类的私有成员。
7. 构造方法可以被继承,但不能被重写。
8. 构造方法不能被声明为final、static或abstract。
22. 静态方法和实例方法有何不同?
Java中的静态方法和实例方法有以下不同点:
1. 静态方法属于类,而实例方法属于对象。静态方法可以通过类名直接调用,而实例方法需要先创建对象才能调用。
2. 静态方法不能访问实例变量和实例方法,只能访问静态变量和静态方法。实例方法可以访问实例变量和实例方法,也可以访问静态变量和静态方法。
3. 静态方法在编译时就已经确定,而实例方法需要在运行时才能确定。
4. 静态方法可以被子类继承和重写,但是静态方法的行为不会发生变化。实例方法也可以被子类继承和重写,但是实例方法的行为会发生变化。
5. 静态方法可以在没有创建对象的情况下使用,比如Math类中的静态方法。实例方法必须要创建对象之后才能使用。
23.对象的相等与指向他们的引用相等,两者有什么不同?
对象的相等是指对象所存储的内容是否相等,引用相等是指引用所指向的地址是否相等。
24.在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
Java 程序在执行子类的构造方法之前,如果没有用 super() 来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super() 来调用父类中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上无参构造方法。
在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
帮助子类做初始化工作。
25.== 与 equals(重要)
对于==而言
==对基本数据类型比较的是值
==对引用数据类型比较的是地址
对于equals方法
Object没有重写的equals方法比较的是地址
String重写的equals方法比较的是字符串是否相同
Integer重写了equals方法,比较的是int值是否相同
答案2
==既可以比较基本类型也可以比较引用类型
对于基本类型就是比较值,对于引用类型就是比较内存地址
equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==,我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals的比较值的错误观点。具体要看自定义类里有没有重写Object的equals方法来判断。通常情况下,重写equals方法,会比较类中的相关属性是否都相等。
26. hashCode 与 equals(重要)
在Java中,每个对象都可以调⽤⾃⼰的hashCode()⽅法得到⾃⼰的哈希值(hashCode),相当于对象的 指纹信息,通常来说世界上没有完全相同的两个指纹,但是在Java中做不到这么绝对,但是我们仍然可 以利⽤hashCode来做⼀些提前的判断,⽐如:
● 如果两个对象的hashCode不相同,那么这两个对象肯定不同的两个对象
● 如果两个对象的hashCode相同,不代表这两个对象⼀定是同⼀个对象,也可能是两个对象
● 如果两个对象相等,那么他们的hashCode就⼀定相同
在Java的些集合类的实现中,在较两个对象是否相等时,会根据上的原则,会先调对象的 hashCode()法得到hashCode进较,如果hashCode不相同,就可以直接认为这两个对象不相 同,如果hashCode相同,那么就会进步调equals()法进较。equals()法,就是来最终 确定两个对象是不是相等的,通常equals法的实现会较重,逻辑较多,hashCode()主要就是得 到个哈希值,实际上就个数字,相对较轻,所以在较两个对象时,通常都会先根据 hashCode想较下。
所以我们就需要注意,如果我们重写了equals()⽅法,那么就要注意hashCode()⽅法,⼀定要保证能遵 守上述规则。
27.为什么 Java 中只有值传递?
Java 中只有值传递是因为 Java 中的参数传递是通过将实参的值复制一份传递给形参的,而不是直接传递实参的引用。因此,无论实参是基本数据类型还是对象类型,都是通过值传递的方式进行参数传递。在传递对象类型的参数时,虽然传递的是对象的引用,但是这个引用的值也是复制了一份传递给形参,因此仍然是值传递。这种方式可以保证程序的安全性和稳定性,避免出现一些不可预测的问题。
28.简述线程,程序、进程的基本概念。以及他们之间关系是什么
线程是程序执行的最小单位,是进程内的一个执行单元。一个进程可以包含多个线程,这些线程共享进程的资源,如内存、文件等。线程之间的切换比进程之间的切换更快,因为线程共享同一进程的地址空间,切换时不需要切换地址空间。
程序是指含有指令和数据的文件,被存储在磁盘或者其他的数据存储设备中,换言之程序是静态的代码,需要被加载到内存中才能执行。程序可以包含多个进程和线程。
进程是指正在运行的程序的实例,是动态的,具有独立的内存空间和系统资源。进程之间是相互独立的,每个进程都有自己的地址空间和资源,进程之间的通信需要通过特定的机制进行。
总的来说,程序是静态的指令集合,进程是指运行这些指令的实例,而线程是进程内的执行单元。程序包含多个进程和线程,进程包含多个线程,线程共享进程的资源。他们之间的关系是程序包含进程和线程,进程包含线程,线程共享进程的资源。
29.线程有哪些基本状态?
1. 新建状态(New): 线程对象被创建后,就进入了新建状态。
例如,Thread thread = new Thread()。
2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
3. 运行状态(Running): 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
4. 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
(02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
(03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5. 死亡状态(Dead): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
30.关于 final 关键字的一些总结
1. final 可以用来修饰类、方法和变量。
2. 用 final 修饰的类不能被继承,用 final 修饰的方法不能被重写,用 final 修饰的变量不能被修改。
3. final 变量必须在声明时或构造函数中进行初始化,不能再次赋值。
4. final 变量可以是基本数据类型,也可以是对象类型。
5. final 方法可以提高性能,因为编译器会将 final 方法转化为内嵌调用。
6. final 类和方法的主要作用是防止被修改或覆盖,保证程序的安全性和稳定性。
7. final 变量的命名规范是全大写字母,多个单词之间用下划线隔开。
8. final 关键字在多线程编程中也有重要作用,可以保证线程安全。
31.Java 中的异常处理
https://blog.csdn.net/pisa8559/article/details/130746434
32.Java 序列化中如果有些字段不想进行序列化 怎么办?
对于不想进行序列化的变量,使用 transient 关键字修饰。
transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。
可以使用transient关键字修饰不想序列化的字段,这样在序列化时就会忽略这些字段。例如:
public class MyClass implements Serializable {
private String name;
private transient int age; // 不想序列化的字段
// ...
}
32.获取用键盘输入常用的的两种方法?
1. 使用Scanner类:
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine(); // 获取一行输入
int num = scanner.nextInt(); // 获取一个整数输入
double decimal = scanner.nextDouble(); // 获取一个浮点数输入
们首先创建了一个Scanner对象,并将System.in作为参数传递给它,表示我们要从标准输入流中获取数据。然后使用nextInt()方法获取一个整数,并将其赋值给变量num。最后输出变量num的值。
2. 使用BufferedReader类:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = reader.readLine(); // 获取一行输入
int num = Integer.parseInt(reader.readLine()); // 获取一个整数输入
double decimal = Double.parseDouble(reader.readLine()); // 获取一个浮点数输入
首先创建了一个BufferedReader对象,并将System.in作为参数传递给它,表示我们要从标准输入流中获取数据。然后使用readLine()方法获取一行字符串,并将其赋值给变量str。最后输出变量str的值。
33.List和Set的区别
List和Set都是Java集合框架中的接口,但是它们有以下几个区别:
1. 有序性:List是有序集合,它按照元素添加的顺序存储元素,可以根据索引访问元素。而Set是无序集合,它不保证元素的顺序,也不能根据索引访问元素。
2. 元素唯一性:List可以存储重复的元素,而Set中不能存储重复的元素,每个元素在Set中只能出现一次。
3. 实现方式:List的常见实现类有ArrayList、LinkedList和Vector,而Set的常见实现类有HashSet、LinkedHashSet和TreeSet。
4. 遍历方式:List可以使用for循环或迭代器遍历元素,而Set只能使用迭代器遍历元素。
总之,List适合存储有序的、可重复的元素,而Set适合存储无序的、不可重复的元素。
34.ArrayList和LinkedList区别
1. 数据结构:ArrayList是基于数组实现的,而LinkedList是基于链表实现的。
2. 访问效率:ArrayList的访问效率比LinkedList高,因为它可以通过下标直接访问元素。而LinkedList需要从头开始遍历链表,直到找到需要的元素。
3. 插入和删除效率:LinkedList的插入和删除效率比ArrayList高,因为它不需要移动其他元素,只需要修改指针即可。而ArrayList需要将后面的元素向后移动或向前移动。
4. 内存占用:LinkedList的每个节点都需要额外的指针来指向下一个节点,因此它的内存占用比ArrayList高。
5. 线程安全:ArrayList不是线程安全的,而LinkedList可以通过Collections.synchronizedList()方法来实现线程安全。
35.HashMap和HashTable有什么区别?其底层实现是什么?
1. 区别:
- 线程安全:Hashtable是线程安全的,而HashMap不是。因为Hashtable的所有方法都是同步的,而HashMap的方法不是同步的,需要自己实现同步。
- null值:Hashtable不允许key或value为null,而HashMap允许key或value为null。
- 性能:HashMap的性能比Hashtable好,因为Hashtable的所有方法都是同步的,导致并发效率低下。
2. 底层实现:
- HashMap底层是基于数组和链表实现的,数组用来存储元素,链表用来解决hash冲突。
- Hashtable底层也是基于数组和链表实现的,但是它的方法都是同步的,使用了synchronized关键字来实现线程安全。