Android 面试专辑Android 面试

Android 面试准备进行曲(Java基础篇) v1.2

2019-09-16  本文已影响0人  _明川

@TOC

update time 2019年9月18日 13:33:09

CSDN地址 (csdn暂时有目录更方便 查找阅读 -。-)

虚拟机 基础

jvm 参考文章

JVM内存管理

JVM执行Java程序的过程:Java源代码文件(.java)会被Java编译器编译为字节码文件(.class),然后JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。

在这里插入图片描述
运行时数据区被分为 线程私有数据区线程共享数据区 两大类:

线程私有数据区包含:程序计数器、虚拟机栈、本地方法栈
线程共享数据区包含:Java堆、方法区(内部包含常量池)

线程私有数据区包含:

线程共享数据区包含:

Java堆和栈的区别

垃圾回收机制/ 回收算法

判定对象可回收有两种方法:

回收算法

分代收集算法:是当前商业虚拟机都采用的一种算法,根据对象存活周期的不同,将Java堆划分为新生代和老年代,并根据各个年代的特点采用最适当的收集算法。

参考文章

Java基础

Java 引用类型

类加载机制

类加载机制:是虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,形成可被虚拟机直接使用的Java类型的过程。另外,类型的加载、连接和初始化过程都是在程序运行期完成的,从而通过牺牲一些性能开销来换取Java程序的高度灵活性。主要阶段:

内存模型

在这里插入图片描述

主内存是所有变量的存储位置,每条线程都有自己的工作内存,用于保存被该线程使用到的变量的主内存副本拷贝。为了获取更好的运行速度,虚拟机可能会让工作内存优先存储于寄存器和高速缓存中。

并发过程中的原子性 时序性

可直接保证的原子性变量操作有:read、load、assign、use、store和write,因此可认为基本数据类型的访问读写是具备原子性的。

若需要保证更大范围的原子性,可通过更高层次的字节码指令monitorenter和monitorexit来隐式地使用lock和unlock这两个操作,反映到Java代码中就是同步代码块synchronized关键字。

通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值这种依赖主内存作为传递媒介的方式来实现。

提供三个关键字保证可见性:volatile能保证新值能立即同步到主内存,且每次使用前立即从主内存刷新;synchronized对一个变量执行unlock操作之前可以先把此变量同步回主内存中;被final修饰的字段在构造器中一旦初始化完成且构造器没有把this的引用传递出去,就可以在其他线程中就能看见final字段的值。

如果在本线程内观察,所有的操作都是有序的,指“线程内表现为串行的语义”;如果在一个线程中观察另一个线程,所有的操作都是无序的,指“指令重排序”现象和“工作内存与主内存同步延迟”现象。

提供两个关键字保证有序性:volatile 本身就包含了禁止指令重排序的语义;synchronized保证一个变量在同一个时刻只允许一条线程对其进行lock操作,使得持有同一个锁的两个同步块只能串行地进入。

Java 主要数据结构

个人实践有限,暂时不整理温习 红黑二叉树

Map

参考文章

HashMap 实际上是一个“链表散列”的数据结构,即数组和链表的结合体。它是基于哈希表的 Map 接口的非同步实现。

数组:存储区间连续,占用内存严重,寻址容易,插入删除困难;
链表:存储区间离散,占用内存比较宽松,寻址困难,插入删除容易;
Hashmap 综合应用了这两种数据结构,实现了寻址容易,插入删除也容易。

在这里插入图片描述

此外列举下 HashMap 的 存取流程图
(唉 那里都有二叉树么)

在这里插入图片描述
  1. 判断键值对数组table[i]是否为空或为null,否则执行resize()进行扩容;
  2. 根据键值key计算hash值得到插入的数组索引i,如果table[i]==null,直接新建节点添加,转向第六步,如果table[i]不为空,转向第三部;
  3. 判断table[i]的首个元素是否和key一样,如果相同直接覆盖value,否则转向第四步,这里的相同指的是hashCode以及equals;
  4. 判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向第五步;
  5. 遍历table[i],判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可;
  6. 插入成功后,判断实际存在的键值对数量size是否超过了最大容量threshold,如果超过,进行扩容,然后结束整个流程。

至于其

  1. HashMap 原理 及 扩容机制 这里暂不展开说明 放上 曾经的参考文章
    HashMap 原理 及 扩容机制 - 参考文章

  2. HashMap 和 ArrayMap 的区别(数组扩容方式 )
    ArrayMap :通过 Hash/ (key/value)的存储方式优化数组空间,一种独特的方式,能够重复的利用因为数据扩容而遗留下来的数组空间

    HashMap : 初始值16个长度,每次扩容的时候,直接申请双倍的数组空间
    ArrayMap : 每次扩容的时候,如果size长度大于8时申请size*1.5个长度,大于4小于8时申请8个,小于4时申请4个。

    HashMap 和 ArrayMap 的区别 - 参考文章

  3. HashMap 和 LinkedHashMap的区别
    LinkedHashMap - 参考文章

  4. 深入LinkedHashMap 了解 LRU 缓存 (个人吃过很多亏)
    LinkedHashMap 及 LRU 缓存 - 参考文章

  5. ConcurrentHashMap 了解吗?(多并发)
    ConcurrentHashMap 参考文章

设计模式 (使用过的)

延伸:Android 中源码使用的设计模式,自己使用过的设计模式

View事件分发: 责任链模式
BitmapFactory加载图片: 工厂模式
ListAdapter: 适配器模式
DialogBuilder: 建造者模式
Adapter.notifyDataSetChanged(): 观察者模式
Binder机制: 代理模式

平时经常使用的 设计模式

单例模式

初级版

public class Singleton {
    private static Singleton instance;
    private Singleton (){}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

进阶版

public class Singleton {
    private volatile static Singleton singleton;//代码1
    private Singleton (){}
    public static Singleton getSingleton() {
        if (singleton == null) {//代码2
            synchronized (Singleton.class) {
                if (singleton == null) {//代码3
                    singleton = new Singleton();//代码4
                }
            }
        }
        return singleton;
    }
}

  在多线程中 两个线程可能同时进入代码2, synchronize保证只有一个线程能进入下面的代码,
  此时一个线程A进入一个线程B在外等待, 当线程A完成代码3 和代码4之后,
线程B进入synchronized下面的方法, 线程B在代码3的时候判断不过,从而保证了多线程下 单例模式的线程安全,
  另外要慎用单例模式,因为单例模式一旦初始化后 只有进程退出才有可能被回收,如果一个对象不经常被使用,尽量不要使用单例,否则为了几次使用,一直让单例存在占用内存

优点:

缺点:

Builder 模式

参考文章

在这里插入图片描述
具体的产品类
public class Computer {
    private String mCPU;
    private String mMemory;
    private String mHD;

    public void setCPU(String CPU) {
        mCPU = CPU;
    }

    public void setMemory(String memory) {
        mMemory = memory;
    }

    public void setHD(String HD) {
        mHD = HD;
    }
}

抽象建造者

public abstract class Builder {
    public abstract void buildCPU(String cpu);//组装CPU

    public abstract void buildMemory(String memory);//组装内存

    public abstract void buildHD(String hd);//组装硬盘

    public abstract Computer create();//返回组装好的电脑
}

创建者实现类

public class ConcreteBuilder extends Builder {
    //创建产品实例
    private Computer mComputer = new Computer();

    @Override
    public void buildCPU(String cpu) {//组装CPU
        mComputer.setCPU(cpu);
    }

    @Override
    public void buildMemory(String memory) {//组装内存
        mComputer.setMemory(memory);
    }

    @Override
    public void buildHD(String hd) {//组装硬盘
        mComputer.setHD(hd);
    }

    @Override
    public Computer create() {//返回组装好的电脑
        return mComputer;
    }
}

调用者

public class Director {
    private Builder mBuild = null;

    public Director(Builder build) {
        this.mBuild = build;
    }

    //指挥装机人员组装电脑
    public void Construct(String cpu, String memory, String hd) {
        mBuild.buildCPU(cpu);
        mBuild.buildMemory(memory);
        mBuild.buildHD(hd);
    }
}

调用


 Director direcror = new Director(new ConcreteBuilder());//创建指挥者实例,并分配相应的建造者,(老板分配任务)
direcror.Construct("i7-6700", "三星DDR4", "希捷1T");//组装电脑

Builder 模式 优缺点

优点

缺点

源码中使用的 比如: Dialog.Builder

工厂模式

在这里插入图片描述

抽象产品类

    public abstract class Product {
        public abstract void show();
    }

具体产品类

    public class ProductA extends Product {
        @Override
        public void show() {
            System.out.println("product A");
        }
    }
    //具体产品类B
    public class ProductB extends Product {
        @Override
        public void show() {
            System.out.println("product B");
        }
    }

创建抽象工厂类

     //抽象工厂类
    public abstract class Factory {
        public abstract Product create();
    }

创建具体工厂类,继承抽象工厂类

    public class FactoryA extends Factory {
        @Override
        public Product create() {
            return new ProductA();//创建ProductA
        }
    }
    //具体工厂类B
    public class FactoryB extends Factory {
        @Override
        public Product create() {
            return new ProductB();//创建ProductB
        }
    }

测试代码

        Factory factoryA = new FactoryA();
        Product productA = factoryA.create();
        productA.show();
        //产品B
        Factory factoryB = new FactoryB();
        Product productB = factoryB.create();
        productB.show();

优点:

缺点:

源码中 使用的 比如 ThreadFactory

观察者模式

参考文章

含义: 定义对象间的一种一个对多的依赖关系,当一个对象的状态发送改变时,所以依赖于它的对象都得到通知并被自动更新。

在这里插入图片描述
备注:

代码实现

抽象观察者

    public interface Observer {//抽象观察者
        public void update(String message);//更新方法
    }

具体观察者

public class Boy implements Observer {

        private String name;//名字
        public Boy(String name) {
            this.name = name;
        }
        @Override
        public void update(String message) {//男孩的具体反应
            System.out.println(name + ",收到了信息:" + message+"屁颠颠的去取快递.");
        }
    }

创建抽象主题

    public interface  Observable {//抽象被观察者
         void add(Observer observer);//添加观察者
 
         void remove(Observer observer);//删除观察者
    
         void notify(String message);//通知观察者
    }

创建具体主题

    public class Postman implements  Observable{//快递员
        
        private List<Observer> personList = new ArrayList<Observer>();//保存收件人(观察者)的信息
        @Override
        public void add(Observer observer) {//添加收件人
            personList.add(observer);
        }

        @Override
        public void remove(Observer observer) {//移除收件人
            personList.remove(observer);

        }

        @Override
        public void notify(String message) {//逐一通知收件人(观察者)
            for (Observer observer : personList) {
                observer.update(message);
            }
        }
    }

测试代码

        Observable postman=new Postman();
        
        Observer boy1=new Boy("路飞");
        Observer boy2=new Boy("乔巴");
        postman.notify("快递到了,请下楼领取.");

优点:

缺点:

Android 源码中的观察者模式:Listener

其他设计模式

由于本人涉猎较少,有些只能说简单了解。这里分享一个 不错的 系列博客,感谢前人栽树。

设计模式系列教程 !!!

源码设计

接口和抽象类

所以:抽象类强调的是重用,接口强调的是解耦。

最后更新时间:2019年9月3日 17:36:35

上一篇下一篇

猜你喜欢

热点阅读