Android常见面试题集锦(一)

292 阅读8分钟

Java基础篇

1. Java 的基本数据类型都有哪些各占几个字节

byte 1、 char 2、 short 2、 int 4、 float 4、 double 8、 long 8、 boolean 1

补充:

(1)在 Java 中,一共有 8 种基本类,每个基本数据类型都对应了一个包装类

(2)包装类的作用:包装类的存在解决了基本数据类型无法做到的事情泛型类型参数、序列化、类型转换、高频区间数据缓存等问题。

image.png

2. String 是基本数据类型吗?可以被继承吗?

String 是引用类型,底层用 char 数组实现的。因为 String 是 final 类,在 java 中被 final 修饰的类不能被继承, 因此 String 当然不可以被继承。

3. int和Integer有什么区别?为什么要有包装类?

(1)数据类型不同:int 是基础数据类型,而 Integer 是包装数据类型;

(2)默认值不同:int 的默认值是 0,而 Integer 的默认值是 null;

(3)内存中存储的方式不同:int 在内存中直接存储的是数据值,而 Integer 实际存储的是对象引用,当 new 一个 Integer 时实际上是生成一个指针指向此对象;

(4)实例化方式不同:Integer 必须实例化才可以使用,而 int 不需要;

(5)变量的比较方式不同:int 可以使用 == 来对比两个变量是否相等,而 Integer 一定要使用 equals 来比较两个变量是否相等。

4. ==和equals的区别

(1)== 是 Java 中的一个操作符,用于比较两个变量的值是否相等。对于基本数据类型(如 int、float 等),== 比较的是它们的值;对于引用类型(如对象),== 比较的是它们在内存中的地址。

(2)equals() 是 Object 类中定义的方法,用于比较两个对象是否相等。默认情况下,equals() 方法与 == 的作用是一样的,即比较两个对象的内存地址。但是,可以通过重写 equals() 方法来改变其行为,使其比较对象的内容而不是地址。

5. 面向对象的理解

继承:继承是从已有类(基类,超类)得到继承信息创建新类(子类,派生类)的过程。

封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。

多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应,如重载和重写

抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。

6. Java 中有几种类型的流

字节流和字符流。字节流继承于 InputStream 和 OutputStream,字符流继承于 InputStreamReader 和 OutputStreamWriter。

7. Serializable 和 Parcelable 区别

(1)Serializable 是Java本身就支持的接口。

(2)Parcelable 是Android特有的接口,效率比实现Serializable接口高效(可用于Intent数据传递,也可以用于进程间通信(IPC))。

(3)Serializable的实现,只需要implements Serializable即可。这只是给对象打了一个标记,系统会自动将其序列化。

(4)Parcelabel的实现,不仅需要implements Parcelabel,还需要在类中添加一个静态成员变量CREATOR,这个变量需要实现 Parcelable.Creator接口。

(5)Serializable 使用I/O读写存储在硬盘上,而Parcelable是直接在内存中读写。

(6)Serializable 会使用反射,序列化和反序列化过程需要大量I/O操作,Parcelable 自己实现封送和解封操作不需要用反射,数据也存放在Native内存中,效率要快很多

8. 抽象类与接口的区别?

(1)抽象类可以提供成员方法的实现细节,而接口中只能存在 public 抽象方法;

(2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的;

(3)接口中不能含有构造器、静态代码块以及静态方法,而抽象类可以有构造器、静态代码块和静态方法;

(4)一个类只能继承一个抽象类,而一个类却可以实现多个接口;

(5)抽象类访问速度比接口速度要快,因为接口需要时间去寻找在类中具体实现的方法;

(6)如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。如果你往接口中添加方法,那么你必须改变实现该接口的类。

(7)接口更多的为了约束类的行为,可用于解耦,而抽象类更加侧重于代码复用。

9. final

final可以声明成员变量、方法、类以及本地变量

(1)final 成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误

(2)final 变量是只读的

(3)final 申明的方法不可以被子类的方法重写

(4)final 类通常功能是完整的,不能被继承

(5)final 变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销

(6)final 关键字提高了性能,JVM 和 Java 应用都会缓存 final 变量,会对方法、变量及 类进行优化

(7)方法的内部类访问方法中的局部变量,但必须用 final 修饰才能访问

10. static

static 关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就 可以通过类名去进行访问。

(1)静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时 会被初始化。

(2)能通过 this 访问静态成员变量吗?所有的静态方法和静态变量都可以通过对象访问 (只要访问权限足够)

(3)static 是不允许用来修饰局部变量

11. String、StringBuffer、StringBuilder

(1)String 是 final 类,不能被继承。对于已经存在的 Stirng 对象,修改它的值,就是重 新创建一个对象

(2)StringBuffer 是一个类似于 String 的字符串缓冲区,使用 append() 方法修改 Stringbuffer 的值,使用 toString() 方法转换为字符串,是线程安全的

(3)StringBuilder 用来替代于 StringBuffer,StringBuilder 是非线程安全的,速度更快

(4)执行速度:StringBuilder > StringBuffer > String

12. 内部类

(1)非静态内部类没法在外部类的静态方法中实例化。

(2)非静态内部类的方法可以直接访问外部类的所有数据,包括私有的数据。

(3)在静态内部类中调用外部类成员,成员也要求用 static 修饰。

(4)创建静态内部类的对象可以直接通过外部类调用静态内部类的构造器;创建非静态的

(5)内部类的对象必须先创建外部类的对象,通过外部类的对象调用内部类的构造器。

13. 匿名内部类

(1)匿名内部类不能定义任何静态成员、方法

(2)匿名内部类中的方法不能是抽象的

(3)匿名内部类必须实现接口或抽象父类的所有抽象方法

(4)匿名内部类不能定义构造器

(5)匿名内部类访问的外部类成员变量或成员方法必须用 final 修饰

14. 抽象和接口

(1)抽象类不能有对象(不能用 new 关键字来创建抽象类的对象)

(2)抽象类中的抽象方法必须在子类中被重写

(3)接口中的所有属性默认为:public static final

(4)接口中的所有方法默认为:public abstract

15. Java 中深拷贝与浅拷贝的区别?

(1)浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。

(2)深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

16. Error 和 Exception 的区别

(1)Error 是系统中的错误,不可预料的,这种异常发生后,会导致程序立即崩溃。只能通过修改代码,使错误不在出现,这种错误 无法被捕获。

(2)Exception 则是可以预料的。在程序中如果过感觉某段代码会出现 异常,则可以使用 try catch 进行捕获 ,或者直接抛出异常。Exception 可分为 编译时异常(CheckedException) 和 运行时异常(RuntimeException)。运行时异常可以 忽略捕获操作(RuntimeException),编译时异常必须使用 try catch 进行捕获。

17. 范型

(1)泛型是对Java语言类型系统的一种扩展,可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,引入泛型,是对Java语言一个较大的功能增强,带来了很多的好处。

(2)类型安全。类型错误现在在编译期间就被捕获到了,而不是在运行时当作java.lang.ClassCastException展示出来,将类型检查从运行时挪到编译时有助于开发者更容易找到错误,并提高程序的可靠性。

(3 消除了代码中许多的强制类型转换,增强了代码的可读性,为较大的优化带来了可能。