android面试笔记

作者: 9dfaf364d57f | 来源:发表于2018-02-01 21:48 被阅读79次

    此篇文章主要记录本人在面试中遇到一些平常习惯但却没注意的知识小点,欢迎评论区指出文章疏漏之处和补充这份面试清单,让面试官怀疑人生:
    (打个标签:写于2018年2月1日,会不断更新此文章,喜欢就给个心吧!)

    目录
    1、switch-case:能使用哪些类型
    2、Integer盲区
    3、关于exception的传递
    4、java集合类框架的基本接口有哪些
    5、取鸡蛋的题目
    6、子线程共用计数器问题
    7、整数相除与精度问题
    8、java中有多少中可以创建线程的方法
    9、简述线程池有几种常用类型,他们的区别是

    1、switch-case:能使用哪些类型

    char、byte、short、int、Character、Byte、Short、Integer、String、枚举(ps:long类型是不可以使用)

    2、Integer盲区:
    Integer i = 100;
    Integer j = 100;
    System.out.print(i == j); //true
    Integer i = 128;
    Integer j = 128;
    System.out.print(i == j); //false
    

    对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。
    原因如下:
    java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100);,而java API中对Integer类型的valueOf的定义如下:

    public static Integer valueOf(int i){
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high){
            return IntegerCache.cache[i + (-IntegerCache.low)];
        }
        return new Integer(i);
    }
    

    java对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了。

    关于int与Integer的区别,请参考http://www.jianshu.com/p/4e1966740255

    3、关于exception的传递
    public class MyClass {
        public static class Test1 extends Exception {
            public Test1(String s) {
                super(s);
            }
        }
        public static class Test2 extends Test1 {
    
            public Test2(String s) {
                super(s);
            }
        }
        public static void main(String[] args) {
            try {
                try {
                    throw new Test2("test");
                } catch (Test1 test1) {
                    System.out.println("inner test1");
                    throw test1;
                }
            }catch (Test2 tes2){
                System.out.println("outter test2");
            }catch (Exception e){
                System.out.println("outter exception");
            }finally {
                System.out.println("Hello world");
            }
        }
    }
    

    运行结果图:


    个人误区:面试时,以为不会被外层Test2分支捕获,以为已经失去了其类型,但是其实传递过程中,是同一对象传递,导致类型其实还是Test2。

    4、java集合类框架的基本接口有哪些

    这张图可以说把我们平常用的容器的关系表现的淋淋尽致(此处借用的是Thinking in Java的图)。
    针对这个问题其实可以回答:

    • Collection接口
      Collection是最基本集合接口,它定义了一组允许重复的对象。Collection接口派生了两个子接口Set和List,分别定义了两种不同的存储方式,如下:
    • 2、 Set接口
      Set接口继承于Collection接口,它没有提供额外的方法,但实现了Set接口的集合类中的元素是无序且不可重复。
      特征:无序且不可重复。
    • 3、 List接口
      List接口同样也继承于Collection接口,但是与Set接口恰恰相反,List接口的集合类中的元素是对象有序且可重复。
      特征:有序且可重复。
      两个重要的实现类:ArrayList和LinkedList
      1)ArrayList特点是有序可重复的(查找更迅速,类比数组)
      2)LinkedList是一个双向链表结构的(删除更迅速,类比链表)
    • 4、Map接口
      Map也是接口,但没有继承Collection接口。该接口描述了从不重复的键到值的映射。Map接口用于维护键/值对(key/value pairs)。
      特征:它描述了从不重复的键到值的映射。
      两个重要的实现类:HashMap和TreeMap
      1)HashMap,中文叫散列表,基于哈希表实现,特点就是键值对的映射关系。一个key对应一个Value。HashMap中元素的排列顺序是不固定的。更加适合于对元素进行插入、删除和定位。
      2)TreeMap,基于红黑书实现。TreeMap中的元素保持着某种固定的顺序。更加适合于对元素的顺序遍历。
    • 5、Iterator接口
      Iterator接口,在C#里有例外一种说法IEnumerator,他们都是集合访问器,用于循环访问集合中的对象。 所有实现了Collection接口的容器类都有iterator方法,用于返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,Iterator接口方法能以迭代方式逐个访问集合中各个元素,并可以从Collection中除去适当的元素。
    Iterator it = collection.iterator(); // 获取迭代器
    while(it.hasNext())     
    {    
       Object obj = it.next(); // 得到下一个元素    
    }
    
    • 6、Comparable接口
      Comparable可以用于比较的实现,实现了Comparable接口的类可以通过实现comparaTo方法从而确定该类对象的排序方式。
    5、取鸡蛋的题目:

    有1篮鸡蛋,
    每次取1个刚好,
    每次取2个剩一个,
    每次取3个剩一个,
    每次取4个剩一个
    每次取5个差一个,
    每次取6个剩三个,
    每次取7个刚好,
    每次取8个剩一个,
    每次取9个刚好,
    至少有多少个鸡蛋?

    public class MyClass {
    
        public static void main(String[] args) {
    
            int targetNumber = 1;
            boolean isGet;
    
            for (; ; ) {
                targetNumber++;
                isGet = (targetNumber % 2 == 1) && (targetNumber % 3 == 0)
                        && (targetNumber % 4 == 1) && (targetNumber % 5 == 4)
                        && (targetNumber % 6 == 3) && (targetNumber % 7 == 0)
                        && (targetNumber % 8 == 1) && (targetNumber % 9 == 0);
                if (isGet) {
                    System.out.println(targetNumber);
                    break;
                }
            }
        }
    }
    

    题目其实不难。。只是当时有点懵。。所以也一起记录

    6、子线程共用计数器问题

    实现两条子线程,其中一子线程每隔1秒对计数器加一(主线程和子线程共用),另一子线程每隔2秒堆计数器加一,并且进行输出,当计数器达到1000时,子线程退出,主线程每隔5秒对计数器值进行输出。

    public class MyClass {
    
        public static void main(String[] args) throws InterruptedException {
    
            Thread thread1 = new ThreadOne();
            Thread thread2 = new ThreadTwo();
            thread1.start();
            thread2.start();
            for (; ; ) {
                Thread.sleep(5_000);
                System.out.println("main:" + MyCounter.count);
            }
    
        }
    
        public static class MyCounter {
            public static int count = 1;
        }
    
        public static class ThreadOne extends Thread {
    
            @Override
            public void run() {
                try {
                    for (; ; ) {
                        sleep(1_000);
                        synchronized (MyCounter.class) {
                            if (MyCounter.count >= 20) {
                                break;
                            }
                            ++MyCounter.count;
                            System.out.println("Thread1:" + MyCounter.count);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static class ThreadTwo extends Thread {
            @Override
            public void run() {
                try {
                    for (; ; ) {
                        sleep(2_000);
                        synchronized (MyCounter.class) {
                            if (MyCounter.count >= 20) {
                                break;
                            }
                            ++MyCounter.count;
                            System.out.println("Thread2:" + MyCounter.count);
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
    
    7、整数相除与精度问题
    public class MyClass {
        public static void main(String[] args) {
            System.out.println(2/3+"");
            System.out.println(2/3f+"");
            System.out.println(2/3d+"");
        }
    }
    

    打印结果已经很明显,就不过多解释;这里多啰嗦几句float和double的区别:

    1. float为单精度,占4个字节,精度是8位有效数字,最后一位会进行四舍五入。
    2. double为双精度,占8个字节,精度是17位有效数字,当不声明时,默认为双精度。
    8、java中有多少中可以创建线程的方法

    https://www.jianshu.com/p/18e20701974a

    9、简述线程池有几种常用类型,他们的区别是

    https://www.jianshu.com/p/47468d6c3d96

    10、java中如何实现线程通讯

    http://www.importnew.com/26850.html

    相关文章

      网友评论

        本文标题:android面试笔记

        本文链接:https://www.haomeiwen.com/subject/qcpjzxtx.html