Java 面试机经(初级篇-04期)_java

Java 面试机经(初级篇-04期)_java_02

 

 

31. 抽象类(abstract class)和接口(interface)有什么异同? 

答案: 

1)抽象类可以有构造方法,接口中不能有构造方法。 

2)抽象类中可以有普通成员变量,接口中没有普通成员变量 

3)抽象类中的抽象方法的访问类型可以是 public,protected,但接口中的抽象方法只能是 public 类型的,并且默认即为public abstract 类型。 

4)抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任 意,但接口中定义的变量只能是public static final 类型。 

5)一个类可以实现多个接口,但只能继承一个抽象类。

 

32. String s = "Hello";s = s + "world!";这两行代码执行后,原始的 String 对象中的内容到底变 了没有? 

答案:

没有。因为 String 被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s 原先指向一个 String 对象,内容是 "Hello",然后我们对s 进行了+操作,那么s 所指向的那个对象是否发生了改变呢?答案是没有。这时,s 不指向原来那个对象了,而指向了另一个 String 对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s 这个引用变量不再指向它了。

 

33. 抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native), 是否可同时被 synchronized 修饰? 

答案: 

都不能. 

  • abstract 与 static abstract:用来声明抽象方法,抽象方法没有方法体,不能被直接调用,必须在子类overriding 后才能使用static:用来声明静态方法,静态方法可以被类及其对象调用 static 与abstract 不能同时使用用static 声明方法表明这个方法在不生成类的实例时可直接被类调用,而abstract 方法不能被调用,两者矛盾

  • abstract 与 native native:用来声明本地方法,该方法的实现由非java 语言实现,比如 C。一般用于java 与外环境交互,或与操作系统交互native 可以与所有其它的java 标识符连用,但是abstract 除外。因为native 暗示这些方法是有实现体的,只不过这些实现体是非java 的,但是abstract 却显然的指明这些方法无实现体。 

  • abstract 与synchronized synchronized:用于防止多个线程同时调用一个对象的该方法,与static 连用可防止多个线程同时调用一个类的该方法abstract 与synchronized 不能同时使用从 synchronized 的功能也可以看出,用synchronized 的前提是该方法可以被直接调用,显然和abstract 不能连用

     

34. 阐述静态变量和实例变量的区别。 

答案: 

静态变量也称为类变量,归全类共有,它不依赖于某个对象,可通过类名直接访问;而实例变量 必须依存于某一实例,只能通过对象才能访问到它。

 

35. static 关键字是什么意思?Java 中可否重写(Override)一个 private 或者 static 方法? 

答案: 

1)static 关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下 被访问。 

2)Java 中static 方法不能被重写,因为方法重写是基于运行时动态绑定的,而static 方法是编译时静态绑定的,static 方法跟类的任何实例都不相关,所以概念上不适用。

 

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

答案:

不可以。如果其中包含对象的 method(),不能保证对象初始化。静态方法只能访问静态成 员,因为 static 变量在 Java 中是属于类的,它在所有的实例中的值是一样的,当类被 Java 虚拟机载入的时候,会对 static 变量进行初始化。如果你的代码尝试不用实例来访问非 static 的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上

 

37. 简述线程,程序、进程的基本概念。以及他们之间关系是什么? 

答案: 

线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产 生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系 统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如 此,线程也被称为轻量级进程。 

程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静 态的代码。 

进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一 个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程 序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行 时,将会被操作系统载入内存中。线程是进程划分成的更小的运行单位。

 

38. 创建线程有几种不同的方式? 

答案: 

有三种方式可以用来创建线程 

1)继承 Thread 类 

2)实现 Runnable 接口 

3)应用程序可以适用 Executor 框架来创建线程池实现了 Runnable 接口这种方式更受欢迎,因为这不需要继承 Thread 类。在应用设计中已经继承了别的对象的情况下,这需要多继承,而 Java 不支持多继承,只能实现接口。同时, 线程池也是非常高效的,很容易实现和适用。举例: 

例 1: 

public class ThreadDemo { 
      public static void main(String[] args) { 
            Runnable task = () -> { 
                try { 
                     for(int i = 5; i > 0; i--) { 
                           System.out.println("Child Thread: " + i); 
                           Thread.sleep(100); 
                     } 
                } catch (Exception e) {
                }
                 System.out.println("child thread exit."); 
              };
             Thread t1 = new Thread(task); 
             System.out.println("Child Thread: " + t1); 
             t1.start(); 
             try { 
                 for(int i = 5; i > 0; i--) { 
                       System.out.println("Main Thread: " + i); 
                       Thread.sleep(100); 
                 } 
             }catch(Exception e) { 
             }
             System.out.println("Main thread exit."); 
        } 
}

例 2:

public class ExecutorsTest{

    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> ft = executor.submit(() -> {
            System.out.println("Hello Thread!");
            return "sucess";
        });
        try {
            System.out.println("return : " + ft.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }
}

 

39. 线程有几种可用状态? 

答案: 

线程在执行过程中,可以处于以下几种状态: 

1)就绪状态(Runnable):线程准备运行,不一定立马就能开始执行; 

2)运行状态(Running):正在执行的线程代码; 

3)等待状态(Waiting):线程处于阻塞状态,等待外部的处理结束; 

4)睡眠状态(Sleeping):线程被强制睡眠; 

5)I/O 阻塞状态(Blocked on I/O):等待 I/O 操作完成;

6)同步阻塞状态(Blocked on Synchronization):等待获取锁; 

7)死亡状态(Dead):线程完成了执行。

 

40. Thread 类的 sleep()方法和对象的 wait()方法都可以让线程暂停执行,它们有什么区别? 

答案: 

sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指 定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束 后会自动恢复。wait()是 Object 类的方法,调用对象的 wait()方法导致当前线程放弃对象的 锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的 notify()方法(或 notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对 象的锁就可以进入就绪状态。