Android面试题汇总(一)

JAVA基础:

1、抽象类和接口区别

关键词定义:抽象类abstract class,接口interface

成员修饰符:抽象类可以是任意类型,接口只能是默认public static final

方法修饰符:抽象类任意类型,接口默认是public不可以用其他修饰

方法实现:抽象类可以有构造方法,抽象方法和具体实现方法,可以有静态代码块,接口只能抽象方法,没有静态代码块和静态方法

继承方式:抽象类单继承,接口可以实现多个

实现方法:抽象类继承子类不是抽象类需要实现抽象方法,接口需要实现所有的抽象方法

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

选择方式:子类都有方法写在抽象类中,即相同的方法封装。子类需要拓展的方法写的接口中,具体的实现类单独去实现接口,可降低耦合度。

2、分别讲讲 final、static 和 synchronized 可以修饰什么,以及修饰后的作用?

final:可以修饰类、方法、成员

        final修饰的类不可以被继承,修饰的方法不能被重写,修饰的成员需要赋值不能被改变,但是成员如果是引用类型那么他将不能引用别的对象,但是其内部的属性值是可以被改变的。

static:可以修饰类、方法、成员
        static修饰内部类这样就不用实现外部类是创建内部类了,static修饰方法这样可以是直接用类.方法来调用,static修饰成员和方法是一样的类.成员获取或者赋值

synchronized:方法、方法块

        synchronized修饰方法,同一时刻只能一个线程进行访问,其他线程会被阻塞直到线程锁被释放。synchronized修饰的代码块也差不多,只是可以使用类锁,如果时类锁方法需要改为静态方法。

3、请简述一下 String、StringBuffer 和 StringBuilder 三者的区别?

String为字符串常量,被创建后无法修改,是线程安全的;因为是final修饰所以不能被继承;String的长度不变,适用于少量操作的字符串

StringBuffer是字符串变量,长度可变,线程安全,适用与多线程下大量字符串操作

StringBuilder是字符串变量,长度可变,线程不安全,适用与单线程下大量字符串操作

字符串操作在执行速度:StringBuilder > StringBuffer > String

4、“equals” 与 “==”、“hashCode” 的区别和使用场景?

==:基本数据类型可以比较值是否相等,如果是引用类型则比较的是地址而不是值。

equals:比较的引用类型中堆内存中真正的值是否相同,但是需要重写equals方法

hashCode:hashCode对比实际上会出现不准确的问题,不同的对象可能hash值是一样的,就是hash冲突。因为equals计算较慢,所以在对比对象的时候首先判断hashCode是否一致,不一致的话就是两个对象不相等,如果一致在去判断equals。

5、Java 中深拷贝与浅拷贝的区别?

克隆:将A实例重新克隆到B实例

浅克隆:将A中的基本数据类型进行值传递,引用类型进行引用传递,2个引用指向同一个堆内存

神克隆:将A中的基本数据类型进行值传递,引用类型复制一份全新的对象,2个引用指向不同的堆内存

6、谈谈 Error 和 Exception 的区别?

Error:是系统性错误,不可以预料的。程序遇到error会直接崩溃,只能排查代码修复

Exception:是异常,可以预料的,可以通过try cacth去捕获或者抛出。异常分为2种,运行时异常和编译时异常,运行时异常忽略异常捕获,编译时异常必须try cacth捕获

7、什么是反射机制?反射机制的应用场景有哪些?

java中的反射机制,是程序运行的时候可以获取和使用到某个类中的所有成员和方法。

应用场景:eventBus框架、Gson框架、Retrofit框架、逆向编程

8、谈谈如何重写 equals() 方法?为什么还要重写 hashCode()?

Object中,equals代表的是==,即地址相同,同样hashCode的计算也是代表地址的hash值。

比如我们自定义A类。这个时候重写了equals我们可以判断他的地址也可以判断他的值,但是如果不重写hashCode方法,某认的hashCode和我们equals代表的含义就不同了默认是object里面的hashCode,计算的是地址。java原则上equals相同的则代表2个对象的hashCode一定相同。

在使用HashMap的时候,例如put或者remove的时候,会判断对象的hashCode、地址和equals联合使用判断对象是否相同。这个时候如果hashCode跟equals不一致则会出现数据问题。

9、IO 流分为几种

字节流

        InputStream(字节输入流)->FileInputStream:read()

        OutputStream(字节输出流)->FileOutputStream:write()

字符流

        Reader(字符输入流)->FileReader:fileReader()

        Writer(字符输出流)->FileWriter:fileWriter()

缓冲流

        字节

        InputStream->FileInputStream->BufferedFileInputStream

        OutputStream->FileOutputStream->BufferedFileOutputStream

        字符

        Reader->FileReader->BufferedReader

        Reader->InputStreamReader(字符转换输入流)字节转字符

        Writer->FileWriter->BufferedWriter

        Writer->OutputStreamWriter(字符转换输出流)字节转字符

对象流

        ObjectInputStream(对象输入流)

        ObjectOutputStream(对象输出流)

打印流

        PrintStream

备注:纯文本用字符流,mp3、word或者其他文件类型用字节流

10、谈谈你对 Java 泛型中类型擦除的理解,并说说其局限性?

擦边就是在编译的时候,所有的泛型会被去掉,默认继承Object

解决的局限:1、ArrayList 加入Integter会编译报错  2、ArrayList 取值的时候会出现类型强转Object->String  3、父类定义泛型,子类实际实现的是重写(不是重载),通过编译器的桥方式

未解决:1、泛型无法是基本数据类型  2、运行时无法知道类型  3、泛型类型(T)无法在静态方法和变量中使用

11、String 为什么要设计成不可变的?

1、常量池问题

字符串创建的时候,如果常量池中被创建了则不会再次被创建,新的引用直接指向已经创建好的。如果说这个值可以被修改,那么其他地方引用可能会出错,所以要保证字符串的唯一性。这也是常量池的优化手段

2、String可以缓存hash值

String的hash值可能被频繁使用,比如HashMap中,如果String不变这样就可以保证Hash值的准确性可以放心缓存,把hash值缓存下来就不需要频繁的生成了也是一种优化策略

3、安全性问题

String通常会代表网球URL或者文件地址等等,如果String变化则不能保证安全性

12、说说你对 Java 注解的理解?

注解:就是一个标识,对代码规范和变量上面打一个标识,注解大概分为3种

source:针对java文件,生成class文件后消失,主要是对代码规范的约束照规范写代码,比如override注解

class:在编译过程中注解生成class文件,跟java生成class文件效率差不多。常见框架butterKnife和ARouter

RunTime:在class文件生成后还是以注解的形式存在,在运行的时候生效,在代码运行的时候通过反编译进行辅助工作,框架xUtils

13、谈一谈 Java 成员变量、局部变量和静态变量的创建和回收时机?

成员变量:存在堆中,随着类对象创建而创建,随着类对象销毁而销毁

静态变量:存在方法区,方法区JVM的一部分。随着类的加载而创建,随着类的回收而回收,但是类只有长时间不使用不关联才有可能被回收,所以静态变量的生命周期特别长几乎不会被回收,因此建议不是共享的变量不要用静态的

局部变量:存在堆中,方法执行的时候创建,执行完标记为可回收

你可能感兴趣的:(java,开发语言)