2017届毕业生安卓面试题-JAVA篇

从零开始-JAVA

JAVA是安卓的应用和框架层的核心,面试也常常提及,是安卓的基础,地基建好后等待OFFER大楼的只差施工了

  • 基础语法
  • 集合框架
  • 线程相关
  • IO相关
  • 设计模式
  • JAVA虚拟机

基础语法

  • 1.switch能否用String类型做参数?
    答:可以,在java7中添加了对String支持,之前不行.tips:不支持double,float,boolean

  • 2.重载和重写的区别?
    答:重载体现了JAVA中的多态性,允许存在同名函数,只要满足参数类型不同
    重写是子类对父类方法的一种覆盖,保留父类的方法,子类定义自己的方法实现

  • 3.java四个基本特性的面试题

    • ( 封装 多态 抽象 继承)

      • 抽象类和接口的区别?(抽象)
        答:语法上:
        抽象类可以有具体实现的方法而接口的方法全部抽象
        一个类只能继承一个抽象类,但是可以实现多个接口
        接口不能有静态的代码块和方法,抽象类可以有
        设计上:
        抽象类更像一种模板的设计,接口是一种行为的规范

      • JAVA多态实现原理
        多态:同一消息根据发送目的的变换而采取多种不同的行为方式
        原理:动态绑定,在运行期动态识别找到合适的方法

  • 4.equals与==的区别?
    答:基本数据类型,都是比较值是否相等
    引用数据类型,equals比较两个对象指向的内存空间的值是否相等,==比较指向的内存空间地址是否相同
    tips:equals被String类重写所以判断的是字符串是否相等

  • 5.Hashcode方法的作用和equals的区别?
    答:hashcode()返回的是对象内存地址通过哈希算法得到的整数值,
    多出现于集合中判断其中是否有相同的元素,当往HashMap中添加元素时,会先用hashcode判断是否同一个元素,若不相同再用equals判断内容

  • 6.String、StringBuffer与StringBuilder的区别?
    答:
    String 不可变 适用场景:少数据量
    StringBuffer可变 线程安全 适用场景:多线程大数据量
    StringBuilder可变 线程不安全 适用场景:单线程大数据量
    底层是Char[]数组实现的

  • 7.final, finally, finalize的区别?
    答:final是修饰符 被修饰的成员无法被继承无法被覆盖无法被修改成员
    finally语句块 多用于异常处理最后的收尾操作
    finalize对象被垃圾回收期回收的时候会调用这个方法

  • 8.JAVA的四种引用类型,用到的场景
    答:
    1.强引用:不会被垃圾回收期回收,即使JVM内存不足会出现崩溃报错也不会被回收,我们经常new一个对象这个就是强引用,若要中断这种引用,可以显式的将对象赋值为null
    2.软引用:当JVM内存不足时会回收,足够不回收
    3.弱引用:被垃圾回收器发现就会被回收 通常可以用在图片的缓存上
    4.虚引用:随时都有可能被回收

  • 9.说说java的反射机制原理以及应用场合?
    答:反射机制即在运行过程中,
    对于任意一个类,可以得到这个类的所有属性和方法
    对于任意一个对象,可以调用它任意的方法和属性
    这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

    出现场景:GSON的序列化和反序列化等,使用源码中一些被hide注解的方法
    (重要的基础:
    类对象: 封装了类的描述信息的对象,类加载的产物,由jvm创建java.lang.Class
      获取类对象的方式:
    1.类名.class 2. 类的对象.getClass() 3. Class.forName("包名.类名"))
    

集合框架集合框架概图

  • 1.Collection 和 Collections的区别?
    答:Collection是集合的接口,实现它的主要有set和list
    Collections是集合的一个帮助类,能帮助排序,搜索,线程安全化等操作

  • 2.ArrayList、LinkedList、Vector的区别?
    答:ArrayList和Vector底层是由数组实现的,而LinkedList底层是由双向链表实现
    Vector在线程安全性上高于ArrayList和LinkedList但代价是效率上变慢
    ArrayList因为在连续的空间中用序号标记位置,索引快,增删需要涉及元素移动,
    LinkedList存在于独立的空间,对象间保存下一个的索引,增删只用记录本项的前后项即可,增删快,查询需要遍历,查询慢

  • 3.HashMap,HashTable的区别?(附加:ConcurrentHashMap)
    答:HashMap实现的是Map接口而HashTable实现Map接口的同时继承Directory类
    HashMap效率高但线程不安全,HashTable效率低但线程安全
    HashMap的key和value都可以为null而HashTable不可以
    ConcurrentHashMap是线程安全的hashmap并不是像HashTable一样每个方法加同步锁
    他将map分成了几个类似于HashTable的有锁segment分段,put和get时根据hashcode值判断在哪个分段进行,安全性上高,性能也高

  • 4.HashMap,HashSet的区别?
    答:HashMap实现是Map接口,HashSet实现Set接口
    HashMap存储方式-键值对,HashSet存储对象
    HashMap由键的HashCode来判断地址是否重复
    HashSet存储对象也是通过HashMap的add键值对,但是键为对象,值为HashSet自身,
    因为HashMap是允许重复值的所以我们需要重写HashCode和equals判断是否唯一,若相同返回false

  • 5.HashMap的底层源码实现
    答:我们增加一组元素时,会根据输入的key值的hashcode计算hash值,根据哈希值得到元素所在数组下标
    ,如果这个位置再数组上有其他元素,以链表形式加入到头部,最先进入的在尾部,如果下标位置没有其他元素就将元素放在这个位置上

从上面的源代码中可以看出:当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。
 
- 6.Fail-Fast机制概述
答:在使用Iterator迭代器的时候,有其他线程修改了map,将会抛出ConcurrentModificationException(并发修改异常).
源码中:Iterator初始化时会将map的modCount修改次数赋值给expectedModCount,
在迭代中判断modCount和expectedModCount是否相等,若不相等就表名修改了map报错

7.LinkedHashSet和HashTable的原理?
LinkedHashSet底层是用LinkedHashMap实现但又有HashSet(不重复)的特点
LinkedHashMap底层原理 是Entry[]数组,而Entry又是一个双向链表

HashTable原理 是安全的HashMap HashMap底层原理 是Entry数组 而Entry是个单链表


线程相关

  • 1.线程和进程的区别?
    答:
    进程是系统资源分配的基本单位
    线程是CPU资源调度的基本单位
    线程是进程内的一个执行单元,也是一个可调度的实体
    进程内的多个线程共享这个进程内的所有资源
    线程之间协同工作需要借助消息通信

  • 2.什么是线程池,线程池的作用是什么?
    答:
    线程池是对线程的一种封装,开辟一块内存区域,批量放入线程,由池管理器统一调度,当有线程任务,从池子取出,执行完再放回线程池中
    作用:能提高线程的复用性,减少线程对象的创建,节约开销
    能有效的控制并发线程,提高资源使用率,避免堵塞
    提供了定期执行,定时执行,控制线程并发数等功能

  • 3.JAVA如何创建线程?
    答:
    1.继承Thread类 再new
    2.实现Runnable接口再将其作为参数传入Thread类的构造方法中 再new
    3.实现Callable接口

  • 4.用户线程和守护线程有什么区别?
    答:用户线程是我们开发者创建的线程,守护线程是服务于用户线程的且与JVM一同关闭退出的的线程 例如:GC线程

  • 5.wait()和sleep()的区别?
    答:wait方法属于Object类 而Sleep方法属于Thread类
    JAVA中每个对象都有对象锁,当调用wait方法时会将这个锁释放其他线程有机会争抢这个锁,系统会将这个对象的资源空间让出,等待调用notify或notifyall方法后再得到这个锁执行任务
    而sleep方法并没有释放掉对象锁,其他线程无法获得,一直保持这个对象的监控,当时间到时再执行任务

  • 6.JAVA多线程同步的方法?
    答:1.同步代码块
    2.同步方法
    3.使用volatile修饰
    4.使用重入锁(ReenreantLock)是对synchronized的扩展
    5.使用ThreadLocal类管理共享变量,这样每个访问得线程都有这个变量副本可以随意修改

  • 7.什么是线程调度器和时间分片?
    答:线程调度器是为Runnable状态的线程分配CPU时间,线程的启动依赖于线程调度器
    时间分片是指将cpu时间分配给线程的过程,可以基于线程优先级和等待时间分配

  • 8.Synchronzied和Lock的区别?
    答:Synchronized是隐式锁 Lock是显式锁
    Synchronized是托管给JVM,Lock是代码控制需要自己开启和关闭
    JAVA6之后Synchronized被又优化了导致与lock性能上相差不大
    Synchronized采用悲观锁机制,独占锁而Lock是乐观锁的机制,假设没有冲突出现错误重试,直到成功


IO相关

集合框架概图

  • 1.JAVA序列化,如何实现序列化和反序列化?
    答:序列化:实现Seralizable接口
    反序列化:实现Externalizable接口

Java虚拟机

  • 1.JVM内存模型以及分区,需要详细到每个区放什么
    答:JVM首先分为两个部分线程私有内存区,线程共享内存区
    线程共享内存区:方法区(里面有常量池),堆
    线程私有内存区:PC程序寄存器,本地方法栈,虚拟机栈

方法区:涉及到类加载的时候,加载进来的类的信息,常量,字段,方法代码等的信息
常量池:方法区的一部分,其中存储的是,字面常量,符号引用等
堆:为对象分配内存
PC程序寄存器:记录正在运行虚拟机字节码的地址
本地方法栈:虚拟机原生方法执行的内存区域
虚拟机栈:方法执行的区域,每个方法执行时会创建栈帧,其中记录着局部变量表,方法返回地址等信息

  • 2.JAVA中堆和栈的区别?
    答:都是数据结构

堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全树。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

堆用来存储对象,栈用来存储局部变量,执行方法
堆是线程共享的,栈是线程私有的

  • 3.介绍下Java GC机制
    答:GC即垃圾收集,负责回收所有不可达的对象的内存空间
    原理:采用有向图的方式记录和管理堆中的所有对象,判断是否可达

  • 4.GC怎么确定某个对象是垃圾?

(1)引用计数法:将一个对象的引用关联计数保存,当引用次数为0则释放
缺陷:无法解决循环引用问题 A-B相互引用永远不为0,无法回收

(2)对象引用遍历(现在大多数 jvm 使用的方法):
从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集

  • 5.java GC是在什么时候,对什么东西,做了什么事情(精华)?

什么时候:
堆内存分为新生代,老年代
新生代分为Eden,Survival from,Survival to 当Eden内存满了发生Minor GC
当升到老年代的对象大于老年代的剩余内存会发生FullGC将清理整个堆空间

对什么东西:对象引用遍历中,通过遍历对象图从根对象开始,不可达的对象

什么事情:垃圾回收器根据不同的算法进行对象的回收

在年轻代中Survival from,Survival to 使用了复制清理算法
具体实现:将Eden和Survival from中的存活的对象赋值到Survival to
然后将前面两个区域对象全部清除,不会产生碎片

在老年代中GC使用标记清理算法
具体实现:先进行一次遍历将可达的标记,第二次遍历不可达的清理
会产生碎片-内存空间不连续
碎片整理:

  • 6.GC的种类?
    1.基于引用计数算法的GC 有对象引用+1,引用完毕-1
    2.基于跟踪收集的GC 从根对象开始遍历对象图,记录可达和不可达的
    3.基于对象跟踪分代收集的GC 将JVM堆中根据对象存活时间分段-年轻代,老年代,永久代
    在不同的分段采取不同的垃圾回收算法

Java有四种类型的垃圾回收器:

串行垃圾回收器(Serial Garbage Collector)
并行垃圾回收器(Parallel Garbage Collector)
并发标记扫描垃圾回收器(CMS Garbage Collector)
G1垃圾回收器(G1 Garbage Collector)


设计模式

设计模式即代码的写法,如何才能写出高质量的代码的总结
- 1.单例模式:一个类只有一个实例,并将其向全局提供
懒汉式:将实例放入静态方法中

 private static MyClass myClass=null;

    private MyClass() {}

    public static MyClass getInstance(){

        if(myClass==null){
            myClass=new MyClass();
        }
        return myClass;
    }

饿汉式 将实例放在成员中

   private static final MyClass myClass=new MyClass();

    private MyClass() {}

    public static MyClass getInstance(){
        return myClass;
    }

登记式:通过map实现(仅了解)

优化安全问题的单例-双重检查锁定

private static volatile MyClass myClass=null;//第一重锁定

    private MyClass() {}

    public static  MyClass getInstance(){
        if(myClass==null){//第一重检查
            synchronized (MyClass.class){//第二重锁定
              if(myClass==null){//第二重检查
                  myClass=new MyClass();
              }
            }
        }
        return myClass;
    }

  • 2.工厂模式:实例化对象的模式,用自己的工厂方法代替new,批量生产对象的模式

简单工厂模式(Simple Factory) 缺点:增加产品需要修改工厂代码,违背开闭原则

public class Factory {  
    public BMW createBMW(int type) {  
        switch (type) {  
        case 320:  
            return new BMW320();  
        case 523:  
            return new BMW523();  
        default:  
            break;  
        }  
        return null;  
    }  
}  

工厂方法模式(Factory Method) 改进:只需生成无需修改

interface BMWFactory {//创建工厂接口
    BMW createBMW();
}

class  BMW320Factory implements BMWFactory{//创建不同的工厂
    @Override
    public BMW createBMW() {
        return new BMW320();
    }
}

class  BMW523Factory implements BMWFactory{
    @Override
    public BMW createBMW() {
        return new BMW523();
    }
}

抽象工厂模式(Abstract Factory) 更加抽象

产品抽象

public interface Engine {//创建发动机
}

class EngineA implements Engine {
    public EngineA(){
        System.out.println("制造-->EngineA");
    }
}
class EngineB implements Engine {
    public EngineB(){
        System.out.println("制造-->EngineB");
    }
}

//空调以及型号
interface Aircondition {
}

class AirconditionA implements Aircondition{
    public AirconditionA(){
        System.out.println("制造-->AirconditionA");
    }
}
class AirconditionB implements Aircondition{
    public AirconditionB(){
        System.out.println("制造-->AirconditionB");
    }
}

工厂抽象

//创建工厂的接口    
public interface AbstractFactory {    
    //制造发动机  
    public Engine createEngine();  
    //制造空调   
    public Aircondition createAircondition();   
}    


//为宝马320系列生产配件    
public class FactoryBMW320 implements AbstractFactory{    

    @Override    
    public Engine createEngine() {      
        return new EngineA();    
    }    
    @Override    
    public Aircondition createAircondition() {    
        return new AirconditionA();    
    }    
}    
//宝马523系列  
public class FactoryBMW523 implements AbstractFactory {    

     @Override    
    public Engine createEngine() {      
        return new EngineB();    
    }    
    @Override    
    public Aircondition createAircondition() {    
        return new AirconditionB();    
    }    
}  

  • 3.适配器模式
    类适配器:创建adapter类继承需要实现特殊功能的类并实现规范接口,即可转型调用
public interface Target {
    public void request();//标准接口
}

// 具体目标类,只提供普通功能
class ConcreteTarget implements Target {
    public void request() {
        System.out.println("putong");
    }
}

// 用户需要的类具有特殊功能
class Adaptee {
    public void specificRequest() {
        System.out.println("teshu");
    }
}

class Adapter extends Adaptee implements Target{

    @Override
    public void request() {
        specificRequest();
    }
}
  class Client {
        public static void main(String[] args) {
            // 使用普通功能类
            Target concreteTarget = new ConcreteTarget();
            concreteTarget.request();

            // 使用特殊功能类,即适配类
            Target adapter = new Adapter();
            adapter.request();
        }
}

对象适配器 在适配器中关联类

// 适配器类,直接关联被适配类,同时实现标准接口  
class Adapter implements Target{  
    // 直接关联被适配类  
    private Adaptee adaptee;  

    // 可以通过构造函数传入具体需要适配的被适配类对象  
    public Adapter (Adaptee adaptee) {  
        this.adaptee = adaptee;  
    }  

    public void request() {  
        // 这里是使用委托的方式完成特殊功能  
        this.adaptee.specificRequest();  
    }  
}  

// 测试类  
public class Client {  
    public static void main(String[] args) {  
        // 使用普通功能类  
        Target concreteTarget = new ConcreteTarget();  
        concreteTarget.request();  

        // 使用特殊功能类,即适配类,  
        // 需要先创建一个被适配类的对象作为参数  
        Target adapter = new Adapter(new Adaptee());  
        adapter.request();  
    }  
}  

  • 4.观察者模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值