Java基础知识
1、String 是最基本的数据类型吗?
基本数据类型包括 byte、int、char、long、float、double、boolean 和short。java.lang.String 类是 final类型的,因此不可以继承这个类、不能修改这个类。为了提高 效率节省空间,我们应该用 StringBuffer类
2、重载和重写的区别
重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类就不能
3、 int 和 Integer 有什么区别
Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java 的原始数 据类型,Integer 是java 为 int提供的封装类。Java为每个原始类型提供了封装类。原始类型
封装类
- boolean Boolean
- char Character
- byte Byte
- short Short
- int Integer
- long Long
- float Float
- double Double
引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型 具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储 , 当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省 值为 null,而原始类型实例变量的缺省值与它们的类型有关。
4、运行时异常与一般异常有何异同?
异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中 可能遇到的异常,是一种常见运行错误。java 编译器要求方法必须声明抛出可能发生的非运 行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。
5、String 和 StringBuffer、StringBuilder 的区别是什么?
可变性:
简单的来说:String类中使用final关键字字符数组来保存字符串,private final char value[],所以String对象是不可变的。而StringBuilder 与 StringBuffer 都继承自AbstractStringBuilder中也是使用字符数组保存字符串char[] value 但是没有用final 关键字修饰,所以这两种对象都是可变的。StringBuilder 与 StringBuffer的构造方法都是调用父类构造方法也就是AbstractStringBuilder实现的,大家可以自行查阅源码。
AbstractStringBuilder.java
abstract class AbstractStringBuilder implements Appendable, CharSequence {
char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
线程安全性:
String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf等公共方法。StringBuffer 对方法加了同步锁或者对调用方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
性能:
每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
对于三者的总结:
- 操作少量的数据 = String
- 单线程操作字符串缓冲区下操作大量数据 = StringBuilder
- 多线程操作字符串缓冲区下操作大量数据 = StringBuffer
6、& 和&& 的区别。
&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。
7、自动装箱与拆箱
装箱:
将基本类型用它们对应的引用类型包装起来
拆箱:
将包装类型转换为基本数据类型
8、final,finally,,finalize 的区别。
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。finally是异常处理语句结构的一部分,表示总是执行。finalize 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法, 可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
9、== 与 equals() 的区别
== :它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的 是内存地址)equals():它的作用也是判断两个对象是否相等。但它一般有两个两种使用情况:情况1:类没有覆盖 equals() 方法,则通过equals() 比较该类的两个对象时,等价于通过 == 比价这两个对象。情况2:类覆盖了equals() 方法。一般,我们都覆盖equals() 方法来两个对象的内容相等;若它们的内容相等,则返回true(即,认为两个对象相等)。
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");
}
}
说明:String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有 就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
10、heap和 stack 有什么区别。
栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式 进行处理。堆是栈的一个组成元素
11、GC是什么?为什么要有GC
GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方, 忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的 GC 功能可以自 动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内 存的显示操作方法。
12、关于final关键字的一些总结
final关键字主要用在三个地方:变量、方法、类。对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的 变量,则在对其初始化之后便不能再让其指向另一个对象。当用final修饰一个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为final方法。使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的 任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。类中所有的private方法都隐式地 指定为fianl。
13、Math.round(11.5)等于多少?Math.round(-11.5)等于多少?Math.round(11.5)==12 Math.round(-11.5)==-11 round方法返回与参数最接近的长整数,参数加 1/2后求其 floor.
14、Obiect类的常见方法总结
Object类是一个特殊的类,是所有类的父类。它主要提供了以下11个方法:
public final native Class<?> getClass()//native方法,用于返回当前运行时对象的Class对象,使用了 final关键字修饰,故不允许子类重写。
public native int hashCode() //native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的 HashMap。public boolean equals(Object obj)//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用户 比较字符串的值是否相等。
protected native Object clone() throws CloneNotSupportedException//naitive方法,用于创建并返回 当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生 CloneNotSupportedException异常。
public String toString()//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个方 法。
public final native void notify()//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视 器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
public final native void notifyAll()//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤醒 在此对象监视器上等待的所有线程,而不是一个线程。
public final native void wait(long timeout) throws InterruptedException//native方法,并且不能 重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。
public final void wait(long timeout, int nanos) throws InterruptedException//多了nanos参数, 这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。所以超时的时间还需要加上nanos毫秒。
public final void wait() throws InterruptedException//跟之前的2个wait方法一样,只不过该方法一直等 待,没有超时时间这个概念
protected void finalize() throws Throwable { }//实例被垃圾回收器回收的时候触发的操作
15、Java的接口和C++ 的虚类的相同和不同处。
由于 Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方 法或属性,现有的单继承机制就不能满足要求。与继承相比,接口有更高的灵活性,因为接 口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性 , 并且接口里面的属性在默认状态下面都是 public static,所有方法默认情况下是 public.一个类 可以实现多个接口。
16、描述一下 JVM加载class文件的原理机制?
JVM 中类的装载是由ClassLoader 和它的子类来实现的,Java ClassLoader 是一个重要的 Java运行时系统组件。它负责在运行时查找和装入类文件的类。
17、char型变量中能不能存贮一个中文汉字? 为什么?能够定义成为一个中文的,因为 java中以 unicode 编码,一个char 占16 个字节,所以 放一个中文是没问题的
18、Java中的异常处理
Java异常类层次结构图
在 Java 中,所有的异常都有一个共同的祖先java.lang包中的 Throwable类。Throwable:有两个重要的子类:Exception(异常) 和 Error(错误) ,二者都是 Java 异常处理的重要子类,各自都包含大量子类。Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无 关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一 般会选择线程终止。
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和 处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错 误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。Exception(异常):是程序本身可以处理的异常。Exception 类有一个重要的子类 RuntimeException。RuntimeException 异常由Java虚拟机抛出。NullPointerException(要访问的变量没有引用任何对象时,抛出该 异常)、ArithmeticException(算术运算异常,一个整数除以0时,抛出该异常)和 ArrayIndexOutOfBoundsException (下标越界异常)。
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。
Throwable类常用方法public string getMessage():返回异常发生时的详细信息public string toString():返回异常发生时的简要描述public string getLocalizedMessage():返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可 以声称本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同public void printStackTrace():在控制台上打印Throwable对象封装的异常信息
异常处理总结try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。catch 块:用于处理try捕获到的异常。finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句 时,finally语句块将在方法返回之前被执行。在以下四种特殊情况下,finally块不会被执行在finally语句块中发生了异常。在前面的代码中用了System.exit()退出程序。程序所在的线程死亡。关闭CPU。
19、获取用键盘输入常用的两种方法
方法1:通过Scanner
Scanner input = new Scanner(System.in);
String s = input.nextLine();
input.close();
方法2:通过BufferdReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
20、接口和抽象类的区别
- 接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),抽象类可以 有非抽象的方法
- 接口中的实例变量默认是 final 类型的,而抽象类中则不一定
- 一个类可以实现多个接口,但多只能实现一个抽象类
- 一个类实现接口的话要实现接口的所有方法,而抽象类不一定
- 接口不能用 new 实例化,但可以声明,但是必须引用一个实现该接口的对象 从设计层面来说,抽象是对类的抽 象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
- 备注:在JDK8中,接口也可以定义静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现 两个接口,接口中定义了一样的默认方法,必须重写,不然会报错。
21、JDK 和 JRE 的区别
Java 运行时环境(JRE)是将要执行 Java 程序的 Java 虚拟机。它同时也包含了执行 applet 需要 的浏览器插件。Java 开发工具包(JDK)是完整的 Java 软件开发包,包含了 JRE,编译器和其他 的工具(比如:JavaDoc,Java 调试器),可以让开发者开发、编译、执行 Java 应用程序。
JRE = JVM + Java核心类库
JDK = JRE + Java开发工具
22、是否可以在 static 环境中访问非 static 变量?
static 变量在 Java 中是属于类的,它在所有的实例中的值是一样的。当类被 Java 虚拟机载入 的时候,会对 static 变量进行初始化。如果你的代码尝试不用实例来访问非 static 的变量, 编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
23、Java 中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?
当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提 供构造函数的情况下,Java 编译器会为这个类创建一个默认的构造函数。
Java 中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数 必须有它自己唯一的参数列表。
Java 不支持像 C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情 况下,Java 不会创建默认的复制构造函数
24、Java中支持多继承吗?
不支持,Java 不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。
25、什么是值传递和引用传递
对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响 源对象的值。
对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对 象所做的改变会反映到所有的对象上。
26、什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?
Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟 机执行的字节码文件。
Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写 或者是重新编译。Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他 特性。
27、Java 面向对象
Java 是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发 的优点:
代码开发模块化,更易维护和修改。代码复用。增强代码的可靠性和灵活性。增加代码的可理解性。面向对象编程有很多重要的特性,比如:封装,继承,多态和抽象。下面的章节我们会逐个 分析这些特性。
继承: 继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在不修 改类的情况下给现存的类添加新特性。
封装:
封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法来改 变它内部的数据。在 Java 当中,有 3 种修饰符:public,private 和 protected。每一种修饰符 给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。
下面列出了使用封装的一些好处:
通过隐藏对象的属性来保护对象内部的状态。提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。禁止对象之间的不良交互提高模块化。
多态:
多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上的操 作可以应用到其他类型的值上面。
抽象:
抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来 创建类。Java 支持创建只暴漏接口而不包含方法实现的抽象的类。这种抽象技术的主要目的 是把类的行为和实现细节分离开。
抽象和封装的区别:
抽象和封装是互补的概念。一方面,抽象关注对象的行为。另一方面,封装关注对象行为的 细节。一般是通过隐藏对象内部状态信息做到封装,因此,封装可以看成是用来提供抽象的 一种策略。
28、Java中实现多态的机制是什么
方法的重写 Overriding 和重载 Overloading 是 Java多态性的不同表现。重写 Overriding 是父类与子类之间多态性的一种表现,重载 Overloading 是一个类中多态性的一种表现。