众安保险---Android 面试

众安保险笔试

1.String 与StringBuilder StringBuffer的区别?

  • String:字符串常量
  • StringBuffer:字符创变量
  • StringBuilder:字符创变量
  • StringBuilder:线程非安全的
  • StringBuffer:线程安全的
  • 三者在执行速度方面的比较:StringBuilder > StringBuffer > String

2.静态代码块 构造代码块 构造方法的执行顺序及注意问题?

  • 静态代码块->构造代码块->构造方法
        public class Test {
        
            private int number=0;
            
            //静态代码块
            static{
                System.out.println("静态代码块执行!");
            }
            
            //构造代码块
            {
                System.out.println("构造代码块执行!");
                number=1;
            }
            
            //构造方法
            public Test(){
                System.out.println("构造方法执行!");
                System.out.println(number);
            }
            
            
            public static void main(String[] args) {
                new Test();
            }
        }

3.Activity的几种启动模式,各自举例说明?

  • standard 标准的启动模式 -mainfest中没有配置就默认标准模式
  • singleTop 单一栈顶模式 - 登录页面
  • singleTask 单一任务栈模式 - Home 主页面
  • singleInstance 单一实例模式 - 小程序 系统Launcher、锁屏键、来电显示等系统应用

4.RecyclerView 几种LayoutManager?

  • LinearLayoutManager 线性布局管理器
  • GridLayoutManager 网格布局管理器
  • StaggeredGridLayoutManager 交错网格布局管理器

5.java中 int 占用几个字节?

类型 字节数 最小值 最大值
boolean 未指定,至少1字节,仅定义为取字面值true或false - -
byte 1 -128(-2^7) 127(2^7-1)
short 2 -32768(-2^15) 32767(2^15 - 1)
char 2 \u0000(即0) \uffff(即65,535)
int 4 -2,147,483,648(-2^31) 2,147,483,647(2^31 - 1)
long 8 -9,223,372,036,854,775,808(-2^63) 9,223,372,036,854,775,807(2^63 -1)
float 4 (指数8位,尾数23位,指数偏移量127) 3.4028235E38 1.4E - 45
double 8 (指数11位,尾数52位,指数偏移量1023) 1.7976931348623157E308 4.9E - 324

6.Activity 冷启动、热启动的时间?

  • 冷启动:
    在启动应用时,系统中没有该应用的进程,这时系统会创建一个新的进程分配给该应用;

  • 热启动:
    在启动应用时,系统中已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程还是保留在后台);

  • 使用命令行:adb shell am start -W com.ubtechinc.cruzr.voicedemo/.home.MainActivity 查看时间

     Status: ok
     Activity: packageName/activityName
     ThisTime: 1298
     TotalTime: 1298
     WaitTime: 1308
     Complete
    

7.画出Handler原理图?

Handler原理

8.算法题 快排 双向链表(二选一)?

  • 快速排序

          public static int[] quickSort(int[] array,int start,int end) {
                  if (start<=end) {
                      int m = start;
                      int n = end;
                      int the_base = the_array[m];
                      while (m=the_base)) {
                              n--;
                          }
                          array[m]=array[n];
                          while((m
  • 双向链表

    public class DoubleLink {
    
    private class Node {
        /**
         * 节点值
         */
    
        private T vlaue;
        /**
         * 前一个节点
         */
        
        private Node prev;
        /**
         * 后一个节点
         */
        
        private Node prex;
        
        public Node(T value,Node prev,Node prex){
            this.vlaue = value;
            this.prev = prev;
            this.prex = prex;
        }
    }
    /**
     * 链表长度
     */
    private int size ;
    /**
     * 头节点
     */
    private Node head;
    public DoubleLink(){
        /**
         * 头结点不存储值 并且头结点初始化时 就一个头结点。
         * 所以头结点的前后节点都是自己
         * 并且这个链表的长度为0;
         */
        head = new Node<>(null, null, null);
        head.prev = head.prex ;
        head = head.prex;
        size = 0;
    }
     public int getSize(){
         return this.size;
     }
     /**
      * 判断链表的长度是否为空
      */
     public boolean isEmplty(){
         return size == 0;
     }
    /**
     * 判断索引是否超出范围
     */
     public void checkIndex(int index){
         if(index<0||index>=size){
             throw new IndexOutOfBoundsException();
         }
         return;
     }
     /**
      * 通过索引获取链表当中的节点
      * 
      */
     public Node getNode(int index){
         /**
          * 检查该索引是否超出范围
          */
         checkIndex(index);
         /**
          * 当索引的值小于该链表长度的一半时,那么从链表的头结点开始向后找是最快的
          */
         if(index cur = head.prex;
             for(int i=0;i cur = head.prev;
         int newIndex = size - (index+1);
         for(int i=0;i cur){
         return cur.vlaue;
     }
     /**
      * 获取第一个节点的值
      */
     public T getFirst(){
         return getValue(getNode(0));
     }
     /**
      * 获取最后一个节点的值
      */
     public T getLast(){
         return getValue(getNode(size-1));
     }
     /**
      * 插入节点
      */
     public void inesert(int index,T value){
         //如果这次插入时 链表是空的
         if(index==0){
             //这个节点的
             Node cur = new Node(value, head, head.prex);
             head.prex.prev = cur;
             head.prex = cur;
             size++;
             return;
         }
         /**
          * 先根据给出的插入位置 找到该链表原来在此位置的节点
          */
         Node node = getNode(index);
         /**
          *放置的位置的前一个节点就是原节点的前置节点 而后节点就是原节点
          */
         Node cur = new Node(value,node.prev,node);
         /**
          * 现将该位置也就是 原节点的前节点的后节点 赋值成为新节点
          * 然后将新节点的后置节点的值赋值成为原节点
          */
         node.prev.prex = cur;
         node.prev = cur;
         size++;
     }
     /**
      * 向表头插入数据
      */
     public void insertTo(T Value)
     {
         inesert(0,Value);
     }
     /**
      * 将元素插入到链表的尾部
      */
     public void insertTotatil(T vlaue){
         Node cur = new Node<>(vlaue,head.prev, head);
        //head.prev 代表原来的尾部节点
         //遵循两个原则 一 新插入节点的前一个节点的后一个节点为新节点。新节点的后一个节点的前一个节点是新节点
         head.prev.prex = cur;
         head.prev = cur;
         size++;
     }
    /**
     * 删除节点的方法
     */
     public void del(int index){
         checkIndex(index);
         Node cur = getNode(index);
         //记住此时的指针还没断开 赋值以后才相当于断开 
         cur.prev.prex = cur.prex;
         cur.prex.prev = cur.prev;
         size--;
         cur = null;
         return;
     }
    /**
     * 删除第一个节点
     */
    public void  delFirst(){
        del(0);
    }
    /**
     * 删除最后一个节点
     */
    public void delLast(){
        del(size-1);
    }
    }
  • 十大经典排序算法最强总结(含JAVA代码实现)

技术面 第一轮

1.首先介绍一下自己

2.讲一讲你做的项目的核心贡献

3.HashMap的源码分析?

  • HashMap实现原理

4.HashTable的实现原理

  • 重点讲一个Hashmap与HashTable的区别

    • Hashtable不允许null key和null value,HashMap允许。
    • Hashtable是线程安全的,HashMap不是线程安全的
    • HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
    • Hashtable继承自Dictionary,HashMap继承自AbstractMap。
    • 两者都实现了Map接口
  • HashTable如何保障线程安全

    • 查看源码,发现对外提供的public方法,几乎全部加上了synchronized关键字
    • Hashtable的性能在多线程环境下会非常低效
    • 建议大家在多线程环境下抛弃Hashtable,改用ConcurrentHashMap
  • Hashtable的初始化

         public Hashtable() {
             this(11, 0.75f);
         }
         
         public Hashtable(int initialCapacity, float loadFactor) {
             if (initialCapacity < 0)
             throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
             if (loadFactor <= 0 || Float.isNaN(loadFactor))
                 throw new IllegalArgumentException("Illegal Load: "+loadFactor);
         
             if (initialCapacity==0)
                 initialCapacity = 1;
             this.loadFactor = loadFactor;
             table = new Entry[initialCapacity];
             threshold = (int)(initialCapacity * loadFactor);
         }
    
    • 在默认构造方法中,调用了Hashtable(int initialCapacity, float loadFactor)方法,初始Hashtable的容量为11,负载因子为0.75,那么初始阈值就是8。这点和HashMap很不同,HashMap在初始化时,table的大小总是2的幂次方,即使给定一个不是2的幂次方容量的值,也会自动初始化为最接近其2的幂次方的容量
  • Hashtable的put方法的实现

          public synchronized V put(K key, V value) {
          // Make sure the value is not null
          if (value == null) {
              throw new NullPointerException();
          }
      
          // Makes sure the key is not already in the hashtable.
          Entry tab[] = table;
          int hash = key.hashCode();
          int index = (hash & 0x7FFFFFFF) % tab.length;
          for (Entry e = tab[index] ; e != null ; e = e.next) {
              if ((e.hash == hash) && e.key.equals(key)) {
              V old = e.value;
              e.value = value;
              return old;
              }
          }
      
          modCount++;
          if (count >= threshold) {
              // Rehash the table if the threshold is exceeded
              rehash();
      
                  tab = table;
                  index = (hash & 0x7FFFFFFF) % tab.length;
          }
      
          // Creates the new entry.
          Entry e = tab[index];
          tab[index] = new Entry(hash, key, value, e);
          count++;
          return null;
          }
    
    • 实现步骤和思路:
      • 禁止null value插入
      • 根据key的hashCode值 与 0x7FFFFFFF求与后得到新的hash值,然后计算其在table中的索引下标
      • 在索引下标下遍历链表,查找key是否已存在,存在则更新value值
      • 如果不存在,判断table.count是否超过阈值,超过则重新rehash,将原元素全部拷贝到新的table中,并重新计算索引下标。rehash后,容量是以前的2倍+1的大小,这点也和HashMap不同,HashMap是2倍。
      • 插入元素时直接插入在链表头部
      • 更新元素计数器

5.https 握手过程?

http和https 握手过程详解

6.TCP为什么需要三次握手?

  • 为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤
  • 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认

7.常见加密算法?

常见的加密算法

8.讲一讲你熟悉的开源框架的源码?

9.Rxjava线程切换的原理?

详解 RxJava2 的线程切换原理

10.多线程同步?

11.怎么优化数据库?

Android Sqlite 优化

12.讲一讲Dart语言的优势?

13.Flutter开发过程中遇到了那些问题?

技术面 第二轮

1.首先介绍一下自己

2.讲一讲你做的项目的核心贡献

3.TCP 长链接,心跳包问题

  • TCP 长链接,心跳包

4.混合开发怎么数据交互的

5.Flutter与原生应用速度对比,具体的多少时间

你可能感兴趣的:(众安保险---Android 面试)