1.什么是泛型擦除
要理解泛型擦除,要先知道什么是泛型,泛型是用来规范对象(包含集合)的参数类型,如ArrayList<String>,来规范传入集合中对象的类型的为String,通过 <? extends T> 或<? super T>来规范其上下边界
泛型擦除也就是泛型的类型擦除,指在编译器中为ArrayList<String> 在转换为class字节码之后就变为ArrayList<Object>,即所有的泛型变量的类型在运行期都会转换为Object
既然理解了泛型擦除的含义,那么它在Java中带来的问题,由于在运行期所有的泛型都会擦除
那么类似的类型检查都会有问题包括:arr instanceOf ArrayList<String> ,new T ,
private <T> T setValue(T t){
//t.call() 编译错误 returun t; }
转换为
private Object setValue(Object t){
//t.call() 编译错误
returun t;
}
因为擦除为Object是没有call方法的,所以在编译器在检查的时候,就会报错
怎么解决类型擦除问题呢?
两种方法.
1.规定泛型的上下边界,用<? extends 接口> 来规定边界
public interface Performs { void speak(); void sit(); } ///:~ class PerformingDog extends Dog implements Performs { public void speak() { print("Woof!"); } public void sit() { print("Sitting"); } public void reproduce() {} } class Robot implements Performs { public void speak() { print("Click!"); } public void sit() { print("Clank!"); } public void oilChange() {} } class Communicate { public static <T extends Performs> void perform(T performer) { performer.speak(); performer.sit(); } } public class DogsAndRobots { public static void main(String[] args) { PerformingDog d = new PerformingDog(); Robot r = new Robot(); Communicate.perform(d); Communicate.perform(r); } }
这样Communicate,在调用的时候就能合理的规避边界问题
2.使用Class类型的方法替代擦除的方法调用
class Building {} class House extends Building {} public class ClassTypeCapture<T> { Class<T> kind; T t; public ClassTypeCapture(Class<T> kind) { this.kind = kind; } public boolean f(Object arg) { return kind.isInstance(arg); } public void newT(){ t = kind.newInstance(); } public static void main(String[] args) { ClassTypeCapture<Building> ctt1 = new ClassTypeCapture<Building>(Building.class); System.out.println(ctt1.f(new Building())); System.out.println(ctt1.f(new House())); ClassTypeCapture<House> ctt2 = new ClassTypeCapture<House>(House.class); System.out.println(ctt2.f(new Building())); System.out.println(ctt2.f(new House())); } }/* Output: true false true
true *///:~
参考:http://www.cnblogs.com/xltcjylove/p/3671943.html
http://blog.csdn.net/lonelyroamer/article/details/7868820
2.Java中静态内部类的初始化的时间?
首先要知道静态内部类的初始化的时候,要明白内部类的含义,什么是内部类,
内部类:在类的内部以嵌套的方式重新创建class,这里的class就是内部类,根据class创建位置的不同分成不同类型的内部类
内部类分类:成员内部类(作为外部类的成员变量,如Activity中Handler) ,局部内部类(在方法中创建的类,随方法的执行完毕,进行回收),匿名内部类(作为new 类名,没有具体类引用,如OnClickListener),静态内部类(由static修饰的类)
内部类从引用上分:静态内部类,非静态内部类(所有的非静态内部类都隐式的持有外部类的引用,这也是造成内存泄漏的主要原因)
从创建(new 对象)方式上,静态内部类,不用依赖外部类的存在而存在,可以单独创建,非静态内部类则不可以
下面在从加载的类的初始化过程
类内部初始化顺序:初始化静态常量 -> 初始化静态代码块 -->类成员变量 --> 类构造方法
继承初始化顺序:静态变量 > 父类 > 子类,
所以有Java中静态内部类的初始化,是和静态变量一致,在类加载的时候进行方法区初始化的,
3.Java中的反射的含义,以及使用场景
反射:Java实施对本身的访问,检测,修改对象的状态和行为的一种能力
对象可以通过反射这种形式修改类的属性和方法,
适用场景:1.暴力反射,对封装对象的访问,
2.xml或properties等配置文件的访问
3.使用动态代理机制创建对象
参考:
http://blog.csdn.net/liujiahan629629/article/details/18013523
http://www.cnblogs.com/luoxn28/p/5686794.html
4 .ListView优化
a.复用converView ,ListView内部实现回收池(RecyclerBin)
b.使用ViewHolder加载
c.图片的三级缓存
5.图片的三级缓存
a.网络缓存
b.内存缓存
c.文件缓存
6.实现缓存的LruCache的原理
LruCache,less retent used 最近最少使用的缓存,策略就是最少使用,最不频繁使用的对象,在内存紧张的时候会回收掉
实现原理:内部使用了LinkedHashMap实现的, LinkedHashMap是由一个LinkedList和一个HashMap组成的,拥有一个双向链表用来存储访问的顺序,HashMap本身存储对象
HashMap实现原理为一个数组 和对应每个数组的项保存了一份单向链表,确认每个数组位置是key的hash值(通过散列算法实现均匀分布),数组的长度确认是hash%length(取模)最新的是hash&(length -1),length的大小总是2的次幂
LinkedHashMap实现原理:一个双向链表保存了对象的位置信息,在双向链表之上(继承)HashMap的Entry(每一项)算法,HashMap来存储其真正的对象
7.关于内存泄漏的知识
什么是内存泄漏:Java虚拟机中对无用对象中仍然存在引用使得垃圾回收器不能回收的内存,就是内存泄漏
内存溢出:Java产生对象的时候。申请分配内存空间时,内存已满,新对象无法获取分配空间的时候,就是内存溢出
内存泄漏的分类:
1.非静态内部类对外部类的默认引用
2.handler的内存泄漏,Handler创建为内部类的时候,默认有对外部类的引用,要创建对象的时候修改为static,并且将外部的引用加入弱引用(WeakRefance)
3.单例模式,单例模式默认是static的,它的生命周期是和Application一样长,不能引用类似于Activity的短生命周期的对象,(加入弱引用)
4.webView的内存泄漏? :打开webView会产生新的线程,默认对Activity有引用,解决方法:?
8.什么是ANR?
ANR是Android not result,客户端没有响应,原因是由于在主线程中进行了耗时操作(不同位置时间不同,activity为5秒),而产生的问题
ANR产生的位置( Activity 5秒,Server 10秒,BroadCastReceiver是20秒)
解决方法:采用工作线程(非主线程)进行耗时操作,使用Handler,HandlerThread,AsychTask,线程池,
9.AsychTask实现原理
10.线程池的四大分类
SingleExectorPool,
CacheExectorPool
11.OkHttp的原理和拥有哪些拦截器
12,Http和https为什么说Https是安全的,是数据传输安全,还是数据本身安全
http://www.voidcn.com/article/p-tmrkwbfg-bch.html