2019年7月Android面试题总结(初中级)附详细答案——Java篇

目录

1.Java的四个基本特性

2.抽象类和接口的区别

3.线程实现的方式

4.什么是重载,什么是重写,有什么区别?

5.关键字 final 和 static 是怎么使用的

6.你所知道的设计模式有哪些

7.如何保证线程安全

8.多线程的等待唤醒主要方法

9.进程的优先级

11.进程和线程的区别

12.Serializable 和Parcelable 的区别

13.成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用

14.List,Set,Map的区别

15.ArrayMap和HashMap的对比

16.HashMap和HashTable的区别

17.ArrayList和LinkedList的区别,以及应用场景

18.数组和链表的区别

19.run()和start()方法区别


汇总一下最近面试碰到的问题,和一些我觉得需要特别注意的问题

Android面试题总结(初中级)附详细答案——Android篇

1.Java的四个基本特性

  • 抽象:把现实生活某一类东西提取出来,成为该类东西的共有特性。抽象一般分为数据抽象和过程抽象,数据抽象是对象的属性,过程抽象是对象的行为特征
  • 封装:把客观事物进行封装成抽象类,该类的数据和方法只让可信的类操作,对不可信的类隐藏。封装分为属性的封装和方法的封装
  • 继承:从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力
  • 多态:同一个行为具有多个不同表现形式或形态的能力,多态的前提是类与类之间必须存在关系,要么继承,要么实现

2.抽象类和接口的区别

  • 抽象类和接口分别给出了不同的语法定义(包括方法体、成员变量修饰符、方法修饰符)
  • 抽象是对类的抽象,接口是对行为的抽象
  • 抽象所体现的是继承关系,是一种”is-a”的关系,接口仅仅实现接口定义的契约,是一种”like-a”的关系
  • 抽象是自底向上抽象的,接口是自顶向下设计出来的

3.线程实现的方式

继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的线程

4.什么是重载,什么是重写,有什么区别?

重载(Overloading):
(1)Overloading 是一个类中多态性的一种表现,让类以统一的方式处理不同类型数据的一种手段。
多个同名函数同时存在,具有不同的参数个数/类型。
(2)重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同,也可以不相
同。无法以返回型别作为重载函数的区分标准。
重写(Overriding):
(1) 父类与子类之间的多态性,对父类的函数进行重新定义。即在子类中定义某方法与其父类有相
同的名称和参数。
(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖
原有的方法。如需父类中原有的方法,可使用 super 关键字,该关键字引用了当前类的父类

5.关键字 final 和 static 是怎么使用的

final 有着“终态的”“这是无法改变的”含义,阻止了多态和继承。
具体使用有:
final 类不能被继承,没有子类,final 类中的方法默认是 final 的。
final 方法不能被子类的方法覆盖,但可以被继承。
final 成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final 不能用于修饰构造方法。
注意:父类的 private 成员方法是不能被子类方法覆盖的,因此 private 类型的方法默认是 final 类型
的。
static 表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态 static 代
码块,但是 Java 语言中没有全局变量的概念。

被 static 修饰的成员变量和成员方法独立于该类的任何对象,static 对象可以在它的任何对象创建之
前访问,无需引用任何对象。
static 前面也可用 public 或 private 来修饰,其中 private 是访问权限限定,static 表示不要实例化
就可以使用。
主要用于静态变量,静态方法,static 代码块
静态变量:对于静态变量在内存中只有一个拷贝(节省内存),JVM 只为静态分配一次内存,在加
载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但
是这是不推荐的)。
静态方法: 静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用 this
和 super 关键字,不能直接访问所属类的实例变量和实例方法(就是不带 static 的成员变量和成员成
员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!
static 代码块:atic 代码块也叫静态代码块,是在类中独立于类成员的 static 语句块,可以有多个,
位置可以随便放,它不在任何的方法体内,JVM 加载类时会执行这些静态的代码块,如果 static 代
码块有多个,JVM 将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次
static 和 final 一起使用:
static final 用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。
特别要注意一个问题:
对于被 static 和 final 修饰过的实例常量,实例本身不能再改变了,但对于一些容器类型(比如,
ArrayList、HashMap)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象,这
一点在编程中用到很多。

6.你所知道的设计模式有哪些

Java 中一般认为有 23 种设计模式,我们不需要所有的都会,但是其中常用的几种设计模式应该去掌
握。下面列出了所有的设计模式。需要掌握的设计模式我单独列出来了,当然能掌握的越多越好。
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元
模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模
式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

6.1单例设计模式

最好理解的一种设计模式,分为懒汉式和饿汉式

饿汉式:

public class Singleton {
// 直接创建对象
public static Singleton instance = new Singleton();
// 私有化构造函数
private Singleton() {
}
// 返回对象实例
public static Singleton getInstance() {
return instance;
}
}

懒汉式:

public class Singleton {
// 声明变量
private static volatile Singleton singleton2 = null;
// 私有构造函数
private Singleton2() {
}
// 提供对外方法
public static Singleton2 getInstance() {
if (singleton2 == null) {
synchronized (Singleton2.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}

6.2工厂设计模式

工厂模式分为工厂方法模式和抽象工厂模式。

1.工厂方法模式

工厂方法模式分为三种:

普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,
则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。
静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即
可。

  • 普通工厂模式
public interface Sender {
public void Send();
}
public class MailSender implements Sender {
@Override
public void Send() {
System.out.println("this is mail sender!");
}
}
public class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
public class SendFactory {
public Sender produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
} else if ("sms".equals(type)) {
return new SmsSender();
} else {
System.out.println("请输入正确的类型!");
return null;
}
}
}

 

  • 多个工厂方法模式

该模式是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确
创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

public class SendFactory {
public Sender produceMail(){
return new MailSender();
}
public Sender produceSms(){
return new SmsSender();
}
}
public class FactoryTest {
public static void main(String[] args) {
SendFactory factory = new SendFactory();
Sender sender = factory.produceMail();
sender.send();
}
}
  • 静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。
public class SendFactory {
public static Sender produceMail(){
return new MailSender();
}
public static Sender produceSms(){
return new SmsSender();
}
}
public class FactoryTest {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.send();
}
}

 

2.抽象工厂模式

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码
 

public interface Provider {
public Sender produce();
}
public interface Sender {
public void send();
}
public class MailSender implements Sender {
@Override
public void send() {
System.out.println("this is mail sender!");
}
}
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("this is sms sender!");
}
}
public class SendSmsFactory implements Provider {
@Override
public Sender produce() {
return new SmsSender();
}
}
public class SendMailFactory implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
public class Test {
public static void main(String[] args) {
Provider provider = new SendMailFactory();
Sender sender = provider.produce();
sender.send();
}
}


6.3建造者模式(Builder)

工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来
创建复合对象,所谓复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式
和最后的 Test 结合起来得到的。

public class Builder {
private List<Sender> list = new ArrayList<Sender>();
public void produceMailSender(int count) {
for (int i = 0; i < count; i++) {
list.add(new MailSender());
}
}
public void produceSmsSender(int count) {
for (int i = 0; i < count; i++) {
list.add(new SmsSender());
}
}
}
public class TestBuilder {
public static void main(String[] args) {
Builder builder = new Builder();
builder.produceMailSender(10);
}
}

7.如何保证线程安全
 

  • 对非安全的代码进行加锁操作
  • 使用线程安全的类
  • 不要跨线程访问共享变量
  • 使用final类型作为共享变量
  • 对共享变量加锁操作

8.多线程的等待唤醒主要方法

  • void notify():唤醒在此对象监视器上等待的单个线程
  • void notifyAll():唤醒在此对象监视器上等待的所有线程
  • void wait():导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法
  • void wait(long timeout):导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量
  • void wait(long timeout, int nanos):导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量

9.进程的优先级

优先级从低到高排列,优先级最高的进程,最先获取资源,最后释放

1、空进程

这是Android系统优先杀死的,因为此时该进程已经没有任何用途

2、后台进程

包含不可见的Activity,即跳转到其他Activity后,由于资源不足,系统会将原来的Activity杀死(即跳转的来源)

3、服务进程

即Service,当系统资源不足时,系统可能会杀掉正在执行任务的Service,因此在Service执行比较耗时的操作,并不能保证一定能执行完毕

4、可见进程

当前屏幕上可以看到的Activity,例如显示一个对话框的Activity,那么对话框变成了前台进程,而调用他的Activity是可见进程,但并不是前台的

5、前台进程

当前处于最前端的Activity,也就是Android最后考虑杀死的对象,一般来说,前台进程Android系统是不会杀死的,只有当前4个都杀掉资源依旧不够才可能会发生
10.java中==和equals和hashCode的区别

基本数据类型的==比较的值相等.

类的==比较的内存的地址,即是否是同一个对象,在不覆盖equals的情况下,同比较内存地址,原实现也为 == ,如String等重写了equals方法.

hashCode也是Object类的一个方法。返回一个离散的int型整数。在集合类操作中使用,为了提高查询速度。(HashMap,HashSet等比较是否为同一个)

如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。

如果两个对象不equals,他们的hashcode有可能相等。

如果两个对象hashcode相等,他们不一定equals。

如果两个对象hashcode不相等,他们一定不equals。

11.进程和线程的区别

进程是cpu资源分配的最小单位,线程是cpu调度的最小单位。

进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。

一个进程内可拥有多个线程,进程可开启进程,也可开启线程。

一个线程只能属于一个进程,线程可直接使用同进程的资源,线程依赖于进程而存在。

12.Serializable 和Parcelable 的区别

Serializable Java 序列化接口 在硬盘上读写 读写过程中有大量临时变量的生成,内部执行大量的i/o操作,效率很低。

Parcelable Android 序列化接口 效率高 使用麻烦 在内存中读写(AS有相关插件 一键生成所需方法) ,对象不能保存到磁盘中

13.成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用

内部类主要分为成员内部类局部内部类(嵌套在方法和作用域内)、匿名内部类(没构造方法)、静态内部类(static修饰的类,不能使用任何外围类的非static成员变量和方法, 不依赖外围类)

使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

因为Java不支持多继承,支持实现多个接口。但有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。

14.List,Set,Map的区别

 

Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。 Set接口主要实现了两个实现类:HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快

TreeSet :TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。

List的特征是其元素以线性方式存储,集合中可以存放重复对象。

ArrayList() : 代表长度可以改变得数组。可以对元素进行随机的访问,向ArrayList()中插入与删除元素的速度慢。

LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。

Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。

HashMap:Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。

LinkedHashMap: 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。

TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。

WeakHashMao :弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。

15.ArrayMap和HashMap的对比

1、存储方式不同

HashMap内部有一个HashMapEntry<K, V>对象,每一个键值对都存储在这个对象里,当使用put方法添加键值对时,就会new一个HashMapEntry对象,

2、添加数据时扩容时的处理不一样,进行了new操作,重新创建对象,开销很大。ArrayMap用的是copy数据,所以效率相对要高。

3、ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,是否空间

4、ArrayMap采用二分法查找;

16.HashMap和HashTable的区别

HashMap不是线程安全的,效率高一点、方法不是Synchronize的要提供外同步,有containsvalue和containsKey方法。

hashtable是线程安全,不允许有null的键和值,效率稍低,方法是是Synchronize的。有contains方法方法。Hashtable 继承于Dictionary 类

17.ArrayList和LinkedList的区别,以及应用场景

ArrayList是基于数组实现的,ArrayList线程不安全。

LinkedList是基于双链表实现的:

使用场景:

(1) 如果应用程序对各个索引位置的元素进行大量的存取或删除操作,ArrayList对象要远优于LinkedList对象;

(2) 如果应用程序主要是对列表进行循环,并且循环时候进行插入或者删除操作,LinkedList对象要远优于ArrayList对象;

18.数组和链表的区别

数组:是将元素在内存中连续存储的;它的优点:因为数据是连续存储的,内存地址连续,所以在查找数据的时候效率比较高;它的缺点:在存储之前,我们需要申请一块连续的内存空间,并且在编译的时候就必须确定好它的空间的大小。在运行的时候空间的大小是无法随着你的需要进行增加和减少而改变的,当数据两比较大的时候,有可能会出现越界的情况,数据比较小的时候,又有可能会浪费掉内存空间。在改变数据个数时,增加、插入、删除数据效率比较低。

链表:是动态申请内存空间,不需要像数组需要提前申请好内存的大小,链表只需在用的时候申请就可以,根据需要来动态申请或者删除内存空间,对于数据增加和删除以及插入比数组灵活。还有就是链表中数据在内存中可以在任意的位置,通过应用来关联数据(就是通过存在元素的指针来联系)

19.run()和start()方法区别

这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值