网易有道Android实习2面面试题+答案

二面:

application里面创建子线程处理耗时任务能不能代替service里面处理耗时任务?

子线程里面能不能创建两个looper?

快速排序(口述)和排序的复杂度?

prim算法?

如何证明贪心算法?

双亲委派模型?

权限关键字的含义,private除了set,get方法访问,还有什么方法?

java中的四种引用

内存泄露和内存溢出的区别

java注解的实现


解答

application里面创建子线程处理耗时任务能不能代替service里面处理耗时任务?
题目很有误导性。service也是运行在主线程中的,处理耗时任务依然要开启子线程。所以问题就变成了这样:application容器可以取代service容器吗?先不讨论这个,先讨论activity容器和service容器的区别。前者如果是后台的容易被杀。application在app的生命周期内,都不会被杀。但是也不意味着可以取代。serivce是依附于进程的,如果它不依附于app进程,而且他所在的进程不被杀,那么他的生命周期可以比application更长。


子线程里面能不能创建两个looper?
当然不行。你在Looper.myLooper()的时候会进行一个创建。然后存放在ThreadLocal里。他首先会进行一个threadLocal.get()的判断,如果不为空,会提示你只能创建一个。


手撸一个快排和计算他的复杂度?
快排就是通过比较著名的挖坑填数法来理解的。(下面的快排代码新手可能得理解好一会了)
void quick_sort(int[] a, int start, int end) {
    int base = a[start];


    int s = start;
    int e = end;
    while(s < e) {
        //从右向左搜,搜到比keng小的数
        while(s < e && base < a[e]) {
            e--;
        if(s < e) {//之所以还要再比一次,不放到循环里比,是为了不想每次循环都做一次运算
            a[s++] = a[e];//坑就是哨兵处
        }
        while(s < e && base > a[s]) {
            s++;
        if(s < e) {
            a[e--] = a[s];
        }
    }
    a[s] = base;//最后初始坑放入最后生成的坑,此时s==e
    //递归
    quick_sort(int[] a, start, i - 1);
    quick_sork(int[] a, i + 1, end);
}
时间复杂度:因为这个是递归的情形,所以最好情况是55分,一次递归会比较n次,深度这样算:n n/2...1
经过k次,1变为n,2^k=n,k=log2n,所以深度是lgn,总复杂度是nlgn
最坏情况是已经排好序的数组,会比n-1次,n-2次,。。。1次,总和是n^2/2
平均情况挺难算的,但是思路也要了解:C(n)=n-1+1/n (C(0)+C(n-1)..)n次的和。第一层是n-1,后面的层数是取一个平均值,这点很容易理解。计算就比较坑了,网上也没有讲解,最后渐进于2nlnn


prim算法和贪心算法的证明?
这两题,我选择不做,因为,没有意义。已经属于偏难怪的范畴了。要是安卓里的偏难怪题我还可以接受


类加载器+双亲委派模型
类加载器:在类加载的时候,需要通过类的全限定名->获取定义这个类的二进制流。
这个二进制流可以从class获取,可以从jar、war获取,可以从网络获取,可以由jsp文件生成。。。
类加载器+和类本身共同确定一个类,如果不是这个类加载器加载的,那么就不是同一个类。所以加载一个类如下:ClassLoaderTest.class.getClassLoader().loadClass("com.jvm.classloading.ClassLoaderTest").newInstance();
先获取这个类的类加载器,再去加载这个类,再去newInstance创建实例。
类加载器种类:从JVM角度,有两种类加载器:1.启动类加载器2.所有其他的类加载器
开发者角度1.启动类加载器,负责加载jar包等类库2.标准扩展类加载器:它负责将Java_Home /lib/ext或者由系统变量 java.ext.dir指定位置中的类库加载到内存中3.应用程序类加载器:将系统类路径(CLASSPATH)中指定的类库加载到内存中4.自定义类加载器
他们之间的层次关系就是:双亲委派模型,除了启动类加载器,其他的都应该有父加载器。
所以当一个加载器接到任务,是一层层向上抛任务的。父类能解决最好,不能解决还是他自己处理。
还有就是找父类的时候,找不到,一般就指定启动类加载器作为父类。
就这么简单,不过得好好理解,好好记忆。


private的属性,除了set和get,还能怎么访问?
太简单了,反射呗。
Class.getDeclaredFields和Class.getDeclaredMethod。
前者是获取所有属性,后者是获取所有方法。
简单写一下吧。
比如Book对象,你想要拿他的一个private的bookName字段。
Field field = book.getClass().getDeclaredFields("bookName");
field.setAccessible(true)。
String bookName = field.get(book).toString();
就好了。注意下那个setAccessible方法,他就是让private的子段,变得可访问。
但是Class.getDeclaredFields拿不到继承的,Class.getField好像可以拿到继承的,但是不能拿到私有的,保护的。


内存泄漏和内存溢出的区别
我觉得内存泄漏你得从垃圾回收机制出发,好好讲讲。还是拿Handler的内存泄漏打比方。Looper,message,message.target=Handler,Activity。依然是可达的,故而不可释放。


注解的实现
我个人感觉这个东西很好用,也用它封装了很多控件。但是我对他的应用还很粗浅--就是简单的指明是运行时注解,指明你要从哪里获取(类上还是方法上还是字段上。。。)然后根据取得的值,进行处理。这是一种很好的封装方式。理解这点,估计暂时够用了。哦,对了,本质还是反射。Class.getAnnotion仍然是在程序运行时,获知了类中的一切,只不过我们获知的东西有点特殊,是依附于某个东西的(类上还是方法上还是字段上。。。)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值