Android面试之Java基础篇
特点和特性
Java特点:跨平台、面向对象、安全性、多线程、简单易用、可维护性高。
特点 | 描述 |
---|---|
跨平台 | Java可以不受计算机的硬件和操作系统的限制,而独立于平台。因为Java中有自带的JVM,它执行经过javac命令编译完成的java源代码所生成的class文件转换成机器码语言在平台上操作。 |
面向对象 | 万物皆对象,Java以对象为基本粒度。对象中包含属性和方法,对象的说明用属性来表达,方法用来操作对象。这样可以对应用程序进行解耦,提高代码的可扩展性和重用性。 |
安全性 | 语言级安全性:Java的数据结构是完整的对象,这些封装过的数据类型具有安全性。 编译时安全性:编译时要进行Java语义和语法的检查,保证每个变量对应一个相应的值,编译后生成Java类。 运行时安全性:表示在运行Java类时要进行字节码校检器校检之后才可以运行。 可执行代码安全性:Java类在网络上使用时,对它的权限进行了设置,保证了被访问用户的安全性。 |
多线程 | 多线程是指允许一个应用程序同时存在两个或两个以上的线程,用于支持事务并发和多任务处理。 Java除了内置的多线程技术之外,还定义了一些类、方法等来建立和管理用户定义的多线程。 |
简单易用 | 就是指java源代码可以不用在特定环境下编写。 |
可维护性高 | — |
四大特性:继承、封装、多态、抽象。
特性 | 描述 |
---|---|
继承 | 继承要有一定的层次结构,还要具备一定的可传递性; 子类只能继承父类非私有化的成员变量和方法; 实行就近原则,有局部变量优先使用局部变量,没有就使用子类成员变量,子类没有则使用父类成员变量。 |
封装 | 将抽象出来的属性和方法写在一个类中就是封装,将不需要对外提供的内容隐藏起来,提供公共的访问方式; 封装就是包装的过程,但封装不是绝对的封装,如果其他程序要获取已经封装好的数据,就要通过程序指定的接口或方法才能获取。 |
多态 | 多态是同一个行为具有多个不同表现形式或形态的能力; 多态就是同一个接口,使用不同的实例而执行不同操作; 多态性是对象多种表现形式的体现。 |
抽象 | 就是对同一类事物共有的属性(特征)和方法(功能/行为)进行抽取、归纳、总结; 抽象类不能实例化为一个对象,就比如水果是苹果,香蕉,梨等一类事物抽象出来的。 |
面向对象和面向过程
面向对象:指的是将问题分解成一个一个步骤,对每个步骤进行相应的抽象,形成对象,然后通过互相调用,解决组合问题;
也就是说在进行面向对象编程的时候,要把属性、行为等封装成对象,然后基于这些对象的能力进行业务逻辑的实现。
面向过程:指的是把问题分解成一个一个步骤,每个步骤用函数来实现,然后依次调用即可。
八大基本数据类型
Java 的两大数据类型:内置数据类型、引用数据类型。
类型 | 描述 |
---|---|
内置数据类型 | byte、short、int、long、float、double、boolean、char |
引用数据类型 | 引用类型指向一个对象,指向对象的变量是引用变量。 对象、数组都是引用数据类型,所有引用类型的默认值都是null。 |
八大基本数据类型占用空间和范围:
类型 | 占用存储空间 | 表示范围 |
---|---|---|
byte | 1字节 | -2^7 ~ 2^7 - 1(-128 ~ 127) |
short | 2字节 | -2^15 ~ 2^15 - 1(-32768 ~ 32767) |
int | 4字节 | -2^31 ~ 2^31 - 1(-2147483648 ~ 2147483647) |
long | 8字节 | -2^63 ~ 2^63 - 1 |
float | 4字节 | -3.403E38 ~ 3.403E38 |
double | 8字节 | -1.798E308 ~ 1.798E308 |
boolean | 1字节 | true、false |
char | 2字节 | 0 ~ 65535 |
四大引用类型
从Java SE2开始,就提供了四种类型的引用:强引用、软引用、弱引用和虚引用。
Java中提供这四种引用类型主要有两个目的:
1、通过代码的方式决定某些对象的生命周期;
2、有利于JVM进行垃圾回收。
类别 | 回收机制 | 用途 | 生存时间 |
---|---|---|---|
强引用 | 从不回收 | 对象状态 | JVM停止运行时 |
软引用 | 内存不足时回收 | 缓存 | 内存不足 |
弱引用 | 对象不被引用时回收 | 缓存 | GC运行后 |
虚引用 | 对象被回收时 | 管理控制精确内存稳定性 | unknown |
常见面试题锦集
equals方法和==的区别
对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址。对于equals方法,注意:equals方法不能作用于基本数据类型的变量;
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
String、StringBuilder和StringBuffer区别
- String、StringBuffer是线程安全的,StringBuilder是非线程安全。
- StringBuffer与StringBuilder的对象存储在堆中,String对象存储在Constant String Pool(字符串常量池)。
- StringBuffer和StringBuilder是可变对象,String一旦创建无法修改,并且String是线程安全的。
为什么String不可变,不可变对象的好处
主要是为了安全。
不可变对象的好处主要也是保证了线程安全。
由于String广泛用于java类中的参数,所以安全是非常重要的考虑点。包括线程安全,打开文件,存储数据密码等等。
因为java字符串是不可变的,可以在java运行时节省大量java堆空间。因为不同的字符串变量可以引用池中的相同的字符串。如果字符串是可变得话,任何一个变量的值改变,就会反射到其他变量,那字符串池也就没有任何意义了。
String的不变性保证哈希码始终一,所以在用于HashMap等类的时候就不需要重新计算哈希码,提高效率。
final、finally、finalize区别
- final:修饰类,方法,变量(表示不可变)。
- finally:finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。
- finalize:finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。
Exception和Error有什么区别
首先Exception和Error都是继承于Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
Exception和Error体现了JAVA这门语言对于异常处理的两种方式。
- Exception是java程序运行中可预料的异常情况,我们可以捕获到这种异常,并且对这种异常进行业务外的处理。
- Error是java程序运行中不可预料的异常情况,这种异常发生以后,会直接导致JVM不可处理或者不可恢复的情况。所以这种异常不能被捕获到,比如OutOfMemoryError、NoClassDefFoundError等。
其中的Exception又分为检查性异常和非检查性异常。
- 检查性异常必须在编写代码时,使用try catch捕获(比如:IOException异常)。
- 非检查性异常在代码编写时,可以忽略捕获操作(比如:ArrayIndexOutOfBoundsException),这种异常是在代码编写或者使用过程中通过规范可以避免发生的。
RunTimeException和其他Exception区别?
其他Exception,受检查异常。可以理解为错误,必须要开发者解决以后才能编译通过,解决的方法有两种:throw到上层或try-catch处理。
RunTimeException:运行时异常,又称不受检查异常,不受检查!不受检查!!不受检查!!!
重要的事情说三遍,因为不受检查,所以在代码中可能会有RunTimeException时Java编译检查时不会告诉你有这个异常,但是在实际运行代码时则会暴露出来,比如经典的1/0,空指针等。如果不处理也会被Java自己处理。
泛型和类型擦除
泛型简单说就是能广泛适用的类型。
还有一种较为准确的说法就是为了参数化类型,就是可以将类型当作参数传递给一个类或者是方法。
- 因为泛型可以使数据的类别像参数一样由外部传递进来,它提供了一种扩展能力,更符合抽象开发。
- 当具体的类型确定后,泛型又提供了一种类型检测的机制,只有相匹配的数据才能正常的赋值,否则编译器就不通过。
- 泛型提高了程序代码的可读性,不必要等到运行的时候才去强制转换。
泛型类中的类型参数与泛型方法中的类型参数是没有相应的联系的,泛型方法始终以自己定义的类型参数为准。
通配符 ?
通配符的出现是为了指定泛型中的类型范围。
- <?>被称作无限定的通配符,会被转译为Object类型。
- <? extends T>被称作有上限的通配符,会被转译为T的类型。
- <? super T>被称作有下限的通配符。
类型擦除
泛型信息只存在于代码编译期间,在编译器编译生成字节码后,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。
在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如
泛型类或者泛型方法中,不接受8种基本数据类型如int、boolean等,而是需要使用它们的包装类Integer、Boolean等。
为什么会有类型擦除?
这是Java实现泛型的方式,也叫作伪泛型。
Java的泛型在底层实现上使用了Object引用,编译器可以通过指定的泛型进行静态类型检查,在编译后又擦除为Object类型。
如果要实现真泛型的话,就需要修改JVM的源码,让虚拟机正确地读取和校验泛型信息,而之前的Java是没有这一概念的。
所以为了兼容旧程序,还需要为原本不支持泛型的API添加一套泛型API。