暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

java面试题及答案(2)关键字

nullPoint水 2018-03-15
188

面试题第二弹,如有问题,欢迎指正

面试题原文链接:https://github.com/tangyouhua/program-resource/blob/master/program-interview/java-baidu-200.md


1.finalize

1.1什么是finalize()方法

    finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。

    finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性,不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。

1.2finalize()方法什么时候被调用

    有三种情况

        1.所有对象被Garbage Collection时自动调用,比如运行System.gc()的时候.

        2.程序退出时为每个对象调用一次finalize方法。

        3.显式的调用finalize方法

1.3finalize的执行过程(生命周期)

    (1) 首先,大致描述一下finalize流程:当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。

    (2) 具体的finalize流程:

        对象可由两种状态,涉及到两类状态空间,一是终结状态空间 F = {unfinalized, finalizable, finalized};二是可达状态空间 R = {reachable, finalizer-reachable, unreachable}。各状态含义如下:

    • unfinalized: 新建对象会先进入此状态,GC并未准备执行其finalize方法,因为该对象是可达的

    • finalizable: 表示GC可对该对象执行finalize方法,GC已检测到该对象不可达。正如前面所述,GC通过F-Queue队列和一专用线程完成finalize的执行

    • finalized: 表示GC已经对该对象执行过finalize方法

    • reachable: 表示GC Roots引用可达

    • finalizer-reachable(f-reachable):表示不是reachable,但可通过某个finalizable对象可达

    • unreachable:对象不可通过上面两种途径可达

    状态变迁图:

    变迁说明:

    1. 新建对象首先处于[reachable, unfinalized]状态(A)

    2. 随着程序的运行,一些引用关系会消失,导致状态变迁,从reachable状态变迁到f-reachable(B, C, D)或unreachable(E, F)状态

    3. 若JVM检测到处于unfinalized状态的对象变成f-reachable或unreachable,JVM会将其标记为finalizable状态(G,H)。若对象原处于[unreachable, unfinalized]状态,则同时将其标记为f-reachable(H)。

    4. 在某个时刻,JVM取出某个finalizable对象,将其标记为finalized并在某个线程中执行其finalize方法。由于是在活动线程中引用了该对象,该对象将变迁到(reachable, finalized)状态(K或J)。该动作将影响某些其他对象从f-reachable状态重新回到reachable状态(L, M, N)

    5. 处于finalizable状态的对象不能同时是unreahable的,由第4点可知,将对象finalizable对象标记为finalized时会由某个线程执行该对象的finalize方法,致使其变成reachable。这也是图中只有八个状态点的原因

    6. 程序员手动调用finalize方法并不会影响到上述内部标记的变化,因此JVM只会至多调用finalize一次,即使该对象“复活”也是如此。程序员手动调用多少次不影响JVM的行为

    7. 若JVM检测到finalized状态的对象变成unreachable,回收其内存(I)

    8. 若对象并未覆盖finalize方法,JVM会进行优化,直接回收对象(O)

    9. 注:System.runFinalizersOnExit()等方法可以使对象即使处于reachable状态,JVM仍对其执行finalize方法

1.4析构函数(finalization)的目的是什么

    在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。一般建议在该方法中释放对象持有的资源。

2.final

2.1final关键字有哪些用法

    final修饰类:

        被final修饰的类,是不可以被继承的,这样做的目的可以保证该类不被修改,Java的一些核心的API都是final类,例如String、Integer、Math等

    final修饰方法:

        子类不可以重写父类中被final修饰的方法

    final修饰实例变量(类的属性,定义在类内,但是在类内的方法之外):

        final修饰实例变量时必须初始化,且不可再修改

    final修饰局部变量(方法体内的变量):

        final修饰局部变量时只能初始化(赋值)一次,但也可以不初始化

    final修饰方法参数:

        final修饰方法参数时,是在调用方法传递参数时候初始化

2.2final 与 static 关键字可以用于哪里?它们的作用是什么

    static关键字:

        static方法:

       1、只能调用其他的static方法

       2、只能使用static变量

       3、不能以任何方式引用this或者super关键字

        (因为静态方法在编译时,最先被加载,所以有他的优势 以及 一定的局限性)因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。

static常常在应用开发中提供一些实用工具类

    static变量

        按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。

当final和static同时使用时,相当于全局常量;

3.final、finalize 和 finally 的不同之处?

    一、性质不同

        (1)final为关键字;

        (2)finalize()为方法;

        (3)finally为为区块标志,用于try语句中;

    二、作用

        (1)final为用于标识常量的关键字,final标识的关键字存储在常量池中;

        (2)finalize()方法在Object中进行了定义,用于在对象“消失”时,由JVM进行调用用于对对象进行垃圾回收,类似于C++中的析构函数;用户自定义时,用于释放对象占用的资源(比如进行I/0操作);

        (3)finally{}用于标识代码块,与try{}进行配合,不论try中的代码执行完或没有执行完(这里指有异常),该代码块之中的程序必定会进行

4.能否在运行时向 static final 类型的赋值

    不能

5.使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变

    使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。

6.一个类被声明为final类型,表示了什么意思

    表示该类不能被继承,不能被修改

7.throws, throw, try, catch, finally分别代表什么意义

    try块表示程序正常的业务执行代码。如果程序在执行try块的代码时出现了“非预期”情况,JVM将会生成一个异常对象,这个异常对象将会被后面相应的catch块捕获。

    catch块表示一个异常捕获块。当程序执行try块引发异常时,这个异常对象将会被后面相应的catch块捕获。

    throw用于手动地抛出异常对象。throw后面需要一个异常对象。

    throws用于在方法签名中声明抛出一个或多个异常类,throws关键字后可以紧跟一个或多个异常类。

    finally块代表异常处理流程中总会执行的代码块。

    对于一个完整的异常处理流程而言,try块是必须的,try块后可以紧跟一个或多个catch块,最后还可以带一个finally块。

    try块中可以抛出异常。

8.java 有几种修饰符?分别用来修饰什么


9.volatile

    volatile让变量每次在使用的时候,都从主存中取。而不是从各个线程的“工作内存”。

    volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,也就是说不保证线程执行的有序性。也就是说,volatile变量对于每次使用,线程都能得到当前volatile变量的最新值。但是volatile变量并不保证并发的正确性。

9.1volatile 变量是什么?

    volatile变量的意思是易变的,它的主要作用是避免编译器优化.volatile简单来讲,就是告诉编译器,在读取该变量数值的时候,应该直接从内存读取,而不是从寄存器读取。

9.2synchronized、volatile、Atomic区别和用法

    可见性:指的是在一个线程中修改变量的值以后,在其他线程中能够看到这个值。

    synchronized关键字除了有互斥的作用外,还有可见性的作用。synchronized保证了synchronized块中变量的可见性,而volatile则是保证了所修饰的变量的可见。因为volatile只是在保证了同一个变量在多线程中的可见性,所以它更多是用于修饰作为开关状态的变量,即Boolean类型的变量。

在jdk5中增加了java.util.concurrent.atomic包,这个包中是一些以Atomic开头的类,这些类主要提供一些相关的原子操作

    Atomic修饰的类进行的操作相对于synchronized修饰的代码块会有很大性能上的提升,建议在计数器相关的多线程并发中用Atomic开头的相关类进行操作。

    总结:volatile多用于修饰类似开关类型的变量、Atomic多用于类似计数器相关的变量、其它多线程并发操作用synchronized关键字修饰。

9.3volatile 类型变量提供什么保证?能使得一个非原子操作变成原子操作吗

    volatile变量对于每次使用,线程都能得到当前volatile变量的最新值。但是volatile变量并不保证并发的正确性。

    能使对long类型和double类型的读取变成原子操作,因为 Java 中读取 long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或 double 变量的读写是原子。

9.4能创建 volatile 数组吗?

    能,Java 中可以创建 volatile 类型数组,不过只是一个指向数组的引用,而不是整个数组。我的意思是,如果改变引用指向的数组,将会受到 volatile 的保护,但是如果多个线程同时改变数组的元素,volatile 标示符就不能起到之前的保护作用了。

10.transient变量有什么特点

    java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

    1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

    2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

    3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

    我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关

11.super什么时候使用

    子类的构造函数中不是必须使用super,在构造函数中,如果第一行没有写super(),编译器会自动插入.但是如果父类没有不带参数的构造函数,或这个函数被私有化了(用private修饰).此时你必须加入对父类的实例化构造.而this就没有这个要求,因为它本身就进行实例化的构造.

    如果父类的构造函数是无参的,那子类构造函数会在第一行默认调用super().

子类调用父类成员变量或方法时。

12.public static void 写成 static public void会怎样

    个人测试貌似没有影响

13.说明一下public static void main(String args[])这段声明里每个关键字的作用

    这是java程序的入口地址,java虚拟机运行程序的时候首先找的就是main方法.跟C语言里面的main()函数的作用是一样的.只有有main()方法的java程序才能够被java虚拟机欲行,可理解为规定的格式

对于里面的参数及修饰符

    public:表示的这个程序的访问权限,表示的是任何的场合可以被引用,这样java虚拟机就可以找到main()方法,从而来运行javac程序

    static:表明方法是静态的,不依赖类的对象的,是属于类的,在类加载的时候main()方法也随着加载到内存中去

    void:main()方法是不需要返回值的

    main:约定俗成,规定的

    String[] args:从控制台接收参数

14.sizeof 是Java 的关键字吗

    不是

15.static

15.1static class 与 non static class的区别

static class

non static class

1、用static修饰的是内部类,此时这个

内部类变为静态内部类;对测试有用;

2、内部静态类不需要有指向外部类的引用;

3、静态类只能访问外部类的静态成员,不能访问外部类的非静态成员;

1、非静态内部类需要持有对外部类的引用;

2、非静态内部类能够访问外部类的静态和非静态成员;

3、一个非静态内部类不能脱离外部类实体被创建;

4、一个非静态内部类可以访问外部类的数据和方法;

15.2Java中是否可以覆盖(override)一个private或者是static的方法

    不可以

15.3静态类型有什么特点

    static特点 1、随着类的加载而加载。也就是说:静态会随着类的消失而消失,说明他的生命周期最长 2、优先于对象存在 3、被所有对象所共享 4、可以直接被类名调用

15.4main() 方法为什么必须是静态的?能不能声明 main() 方法为非静态

    不能,main()方法必须声明为静态的,这样JVM才可以调用main()方法而无需实例化它的类。

    如果从main()方法去掉“static”这个声明,虽然编译依然可以成功,但在运行时会导致程序失败。

15.5是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用

    不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。

15.6静态变量在什么时候加载?编译期还是运行期?静态代码块加载的时机呢

    当类加载器将类加载到JVM中的时候就会创建静态变量,这跟对象是否创建无关。静态变量加载的时候就会分配内存空间。静态代码块的代码只会在类第一次初始化的时候执行一次。一个类可以有多个静态代码块,它并不是类的成员,也没有返回值,并且不能直接调用。静态代码块不能包含this或者super,它们通常被用初始化静态变量。

16.switch 语句中的表达式可以是什么类型数据

    在switch(expression)中,expression只能是一个整数表达式或者枚举常量,整数表达式可以是int类型或Integer包装类型。由于,byte,short,char都可以隐式转换为int类型,所以,这些类型也可以用作表达式。

    另外jdk7以后,switch表达式也可以为String类型,具体原理参考这位大神的博客。

17.while循环和do循环有什么不同

    while是先判断在执行如果判断不成立,就不会执行;do/while是先执行在判断,不管判断是否成立都会执行一次



文章转载自nullPoint水,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论