Java面试----01.JavaSE
1.面向对象和面向过程的区别
- 面向过程:面向过程性能比面向对象高。 因为类调用时需要实例化,比较消耗资源,所以当性能是最重要的考虑因素时,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发。
- 面向对象:面向对象易维护、易复用、易扩展。 面向对象有封装、继承、多态的特征,所以可以设计出低耦合的系统,使系统更加的灵活、更易于维护。
2.Java语言的特点
- 可靠性
- 安全性
- 简单易学
- 面向对象
- 与平台无关
- 支持多线程
- 支持网络编程
- 编译与接受并存
3.Java中JDK、JRE、JVM的区别
- JDK:Java开发工具包(Java Development Kit),它是功能齐全的Java SDK,它包含JRE和编译器(Javac)和工具,它可以创建和编译程序。
- JRE:Java运行环境(Java Runtime Environment),它是运行已编译的Java程序所需要的所有内容集合,包括了JVM和Java类库等,它不能创建新程序。
- JVM:Java虚拟机(Java virtual machine),它是运行Java字节码的虚拟机。
4. Java和C++的区别
- 都是面向对象的语言,都支持封装、继承、多态
- Java不提供指针来直接访问内存,程序内存更加安全
- Java类是单体继承,C++支持多重继承
- Java有自动内存管理机制,不需要手动释放无用内存
5. 什么是Java程序的主类应用程序和小程序的主类有何区别?
- 一个程序中可以有多个类,但只有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序的执行入口点。
6. Java应用程序与小程序之间的区别
- 简单来说应用程序是从主线程启动(main()方法)。applet小程序没有main方法,主要是嵌在浏览器页面上运行。(调用init()或者run()来启动)
7. 字符串常量和字符型常量的区别。
- 形式上:字符串常亮是双引号引起来的若干字符串,字符常量是单引号引起来的一个字符。
- 含义上:字符串常量代表一个地址值,该地址值在内存中存放位置,字符常量相当于一个整型值,可以参加表达式运算。
- 占内存:字符串常量占若干个字节,字符常量只占2个字节。
8. 构造器Constructor是否可以重写override?
- 父类的私有属性和构造方法不能被继承,所以Constructor也是不能被override重写,但是可以被overload重载,所以一个类中可以有多个构造器。
9. 重载、覆盖和重写的区别
- 重载发生在同一个类里面两个或者多个方法的方法名相同但是参数不同的情况。重载Override是一个类中多态性的一种表现。
- 覆盖是说子类重新定义了父类的方法,方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖又叫做重写。
10. 面向对象的三大特性
- 封装:封装就将对象的属性和行为抽象出来包装到类中。
- 继承:继承就是将具有相同属性和行为对象抽象出来并包装成一个父类。
- 多态:多态就是多种形态,相同的属性和行为有不同的表现方式。
封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法。继承中子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法是无法访问的,只是拥有,子类可以对父类进行扩展,拥有自己的属性和方法。在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)、接口(实现接口并覆盖接口中同一方法)。
11. 自动装箱和自动拆箱
- 装箱:将基本类型用它们对应的引用类型包装起来。
- 拆箱:将包装类型装换为基本数据类型。
12. String、StringBuffer和StringBuild的区别是什么,String为什么是不可变的。
- String 类中使用 final 关键字修饰字符数组来保存字符串,所以 String 对象是不可变的。
- 而StringBuilder 与 StringBuffer 都继承AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串但是没有用 final 关键字修饰,所以这两种对象都是可变的。
- StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的。
- String 中的对象是不可变的,也就可以理解为常量,线程安全。
- StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
- StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
- 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。
- StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。
- 相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
- 对于三者使用的总结:
- 操作少量的数据: 适用String
- 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
- 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer
13. 在一个静态方法内调用一个非静态成员为什么是非法的?
- 由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。
14. 在Java中定义一个不做事且没有参数的构造方法的作用。
- 父类中存在有参构造函数时,不会默认生成无参构造函数。同时子类中构造函数没有显式的调用父类的构造函数,则会调用无参构造函数,父类中没有无参构造函数则会报错。
15. 接口和抽象类的区别是什么?
- 抽象类要被子类继承,接口要被类实现。
- 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
- 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
- 接口是设计的结果,抽象类是重构的结果。
- 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
- 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
- 抽象类主要用来抽象类别,接口主要用来抽象功能。
16.成员变量和局部变量的区别:
- 成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;
- 成员变量可以被修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;
- 成员变量和局部变量都能被 final 所修饰。
- 在内存中的位置不同
- 成员变量:在堆中
- 局部变量:在栈中
- 生命周期不同
- 成员变量:随着对象的创建而存在,随着对象的消失而消失
- 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
- 初始化值不同
- 成员变量:有默认值
- 局部变量:没有默认值,必须定义,赋值,然后才能使用
17. 什么是方法的返回值?返回值在类的方法里的作用是什么?
- 方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!
- 返回值的作用:接收出结果,使得它可以用于其他的操作!
18. 一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?
- 主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。
19. 构造方法有那些特性?
- 名字和类名相同
- 没有返回值,不能用
void
声明构造方法 - 生成类的对象时自动执行,无需调用
20. 静态方法和实例方法有何不同?
- 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
- 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
21. 对象的相等与指向他们的引用相等,两者有什么不同?
- 对象的相等,比的是内存中存放的内容是否相等。
- 引用相等,比较的是他们指向的内存地址是否相等。
22. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
- 帮助子类做初始化工作。
23. ==与equals
- 基本类型,== 比较的是值是否相等
- 引用类型,== 对比它们的内存地址是否相等
- equals(),引用类型:默认情况下,对比它们的地址是否相等
- 如果equals()方法被重写,则根据重写过程来比较
24. hashCode 与 equals
- hashCode() 的作用就是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
- 如果两个对象相等,则hashcode一定也是相同的
- 两个对象相等,对两个对象分别调用equals方法都返回true
- 两个对象有相同的hashcode值,它们也不一定是相等的
- 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
- hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等
25. 简述线程、程序、进程的基本概念。以及他们之间关系是什么?
- 线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。
- 程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
- 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。
26. 关于 final 关键字的一些总结
- final关键字主要用在三个地方:变量、方法、类。
- 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;
- 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
- 当用final修饰一个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为final方法。
- 使用final方法的原因:
- 第一个原因是把方法锁定,以防任何继承类修改它的含义;
- 第二个原因是效率。类中所有的private方法都隐式地指定为final。
27. Java 中 IO 流分为几种?
- 按照流的流向分,可以分为输入流和输出流;
- 按照操作单元划分,可以划分为字节流和字符流;
- 按照流的角色划分为节点流和处理