美文网首页
Android面试Java基础篇(三)

Android面试Java基础篇(三)

作者: 肖义熙 | 来源:发表于2021-03-23 13:36 被阅读0次
    问:什么是泛型,泛型擦除是什么,泛型的作用

    答:泛型就是参数化类型,适用于多种数据类型执行相同代码,在使用时才确定真实类型。泛型有泛型类、泛型接口、泛型方法。
    泛型擦除:泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,这叫做泛型擦除。在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如 <T>则会被转译成普通的 Object 类型,如果指定了上限如 <T extends String>则类型参数就被替换成类型上限

    问:什么是反射,反射的使用场景

    答:使用反射,能在运行状态时,对于任意一个类,都能够知道这个类的所有属性和方法、类信息;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态能力称为反射机制。
    类加载过程是 new 一个类时,JVM会加载相应xxx.class到内存中并创建class对象。反射是获取class对象反向获取类信息的过程。
    反射获取class对象的三种方式:以Student类为例

            //第一种方式获取Class对象   少用,都能拿到对象了,不需要反射...
            Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
            Class stuClass = stu1.getClass();//获取Class对象
            System.out.println(stuClass.getName());
            
            //第二种方式获取Class对象    ----需要导包
            Class stuClass2 = Student.class;
            System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
            
            //第三种方式获取Class对象,也是最常用的一种方式
            try {
                Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
                System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
    问:ClassLoader相关

    答:ClassLoader即类加载器,在Android中两个主要的实现类DexClassLoader和PathClassLoader,他们都继承自BaseDexClassLoader,PathClassLoader只能加载已安装的APK的dex, DexClassLoader可以加载APK、DEX、JAR,也可以从SD卡中加载class。在加载类前先判断是否加载过,如果已经加载过直接返回,如果没有加载过找父类加载,父类无法加载的情况下再交给自身进行加载,即双亲委托机制。

    双亲委托机制是指先委托父加载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并加载目标类。这样一方面可以避免重复加载,另一方面可以避免有人恶意编写一个类(如java.lang.String)并加载到JVM中,java.lang.String永远都是由根加载器来加载。

    ClassLoader双亲委托机制在热修复方面使用比较多,一个ClassLoader可以有多个DEX文件,每个Dex文件是一个Element,多个Dex文件排成一个有序数组dexElements,当找类的时候,会按照顺序遍历DEX文件,然后从当前遍历的DEX文件中找类,由于双亲委托模型机制,只要找到就会停止查找并返回,如果找不到就从下一个DEX文件继续查找。只要我们先加载修复好的DEX文件,那么就不会加载有bug的DEX文件了。

    问:简述JVM垃圾回收机制及常见垃圾回收算法

    答:Java运行时内存区域主要划分为:程序计数器,Java虚拟机栈,本地方法栈,方法区和堆五部分。而前三个是伴随线程而生,随线程而死。所以垃圾回收的主要区域为方法区和堆。
    jvm识别垃圾一般有两种方法:

    1. 引用计数法:增加一次引用,计数器+1, 引用失效时,计数器-1,当计数器为0时,视作垃圾,等待回收。
    2. 可达性分析法:活跃的引用对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为GC Roots引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(不可达)时,则证明此对象是不可用的,等待回收

    垃圾回收算法:
    1. 标记清除算法:标记与清除两个流程,有两个缺点:标记和清除这两个步骤的效率都比较低。清除的效率低是因为需要扫描整个内存空间,逐个释放对象所占内存;标记清除之后会产生大量不连续的内存碎片。当程序需要分配较大内存时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作
    2. 复制算法:将内存区域划分为两个部分,每次只使用其中的一快,当要回收部分内存时,复制存活对象到另一块上,然后将整个内存块回收,成为新的保留区,这样不断地循环。缺点:每次都需要浪费一半的内存不使用,内存空间利用率低。
    3. 标记整理算法:与标记清除算法类似,只是在清除前将需要清除的对象内存先进行移动整理成连续的再进行回收,解决了标记清除算法的内存碎片问题。
    4. 分代回收算法:根据对象存活周期的不同将内存划分为新生代和老年代两部分,新生代和老年代的内存大小比例为:1:2,即新生代占用1/3,老年代占用2/3。新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,所以新生代使用复制算法,同时新生代划分为三个块,比例大概为8:1:1。老年代中每次垃圾回收的量较少,所以会采用标记整理算法来进行垃圾回收。

    相关文章

      网友评论

          本文标题:Android面试Java基础篇(三)

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