Android 面试复习

try catch

 public static int getNum() {
        try {
            int a = 1 / 0;
            return 1;
        } catch (Exception e) {
            System.out.println("1");
//            int b = 2 / 0;
//throw new Exception("asdasd");
            System.out.println("2");
            return 2;
        } finally {

            return 5;
        }
    }
复制代码

总结: catch 中,遇到 return 或者再发生 catch ,将会直接执行 finally, 如果没有 finally 只有 再发生 catch 那就抛出异常。

toast :

这是因为Toast显示需要NotificationManagerService(查看Android源码)

部分手机把通知权限关闭了,所以Toast无法正常弹出
复制代码

线程问题:

1,wait 和 sleep 的区别

wait 会释放锁,sleep 会有持有锁。wait 用来线程间交互,sleep 用于暂停执行。
复制代码

2,synchronized 和 volatile volatile:

1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改某个变量的值,这新值对于其他线程可见。(线程缓存无效,取主存中的值,具有原子性)

2)禁止进行指令重排

发散:
1.原子性
    i = 1 这种操作,i ++, j = i 都不是原子操作  
2.可见性
    Java就是利用volatile来提供可见性的。 当一个变量被volatile修饰时,那么对它的修改会立刻刷新到主存,当其它线程需要读取该变量时,会去内存中读取新值。而普通变量则不能保证这一点。
    其实通过synchronized和Lock也能够保证可见性,线程在释放锁之前,会把共享变量值都刷回主存,但是synchronized和Lock的开销都更大。
3.有序性
    JMM是允许编译器和处理器对指令重排序的,但是规定了as-if-serial语义,即不管怎么重排序,程序的执行结果不能改变。
    JMM保证了重排序不会影响到单线程的执行,但是在多线程中却容易出问题。
    
例子:
    1,单例模式的实现,典型的双重检查锁定(DCL)   
    2,标记变量
复制代码

3,线程池

1,线程池优势

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 

第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。 

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定
性,使用线程池可以进行统一的分配,调优和监控。


2,线程池策略

    a. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
    
    b. 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列。
   
    c. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建线程运行这
    个任务;
    
    d. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者“我不能再接受任务了”。
    
    注意:
    
    1、当一个线程完成任务时,它会从队列中取下一个任务来执行。
    
    2、当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于
    corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
复制代码

4,如何控制某个方法允许并发访问线程的个数

Semaphore
semaphore.acquire();
semaphore.release();
复制代码

5,反射

ava 中的反射首先是能够获取到 Java 中要反射类的字节码,获取字节码有三种方法, 1.Class.forName(className) 2.类名.class 3.this.getClass()。然后将字节码中的方法,变量,构造函数等映射 成相应的 Method、Filed、Constructor 等类,这些类提供了丰富的方法可以被我们所使用。

1)动态代理
复制代码
final List<String> list = new ArrayList<String>();
List<String> proxyInstance = (List<String>) Proxy.newProxyInstance(list.getClass().getClassLoader(), list.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {
return method.invoke(list, args); }
}); proxyInstance.add("你好"); System.out.println(list);
复制代码
2)动态代理与静态代理的区别
    静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。 静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。 动态代理是实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是你的
业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。
还有一种动态代理 CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行
时,动态修改字节码达到修改类的目的。
AOP 编程就是基于动态代理实现的,比如著名的 Spring 框架、Hibernate 框架等等都是动态代理的使用例子。
复制代码

转载于:https://juejin.im/post/5cb76a96f265da035d0c740e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值