java面试题之一

  1. 为什么要使用接口?
    1. 由于java里面类的继承是单继承,为了实现多基础,我们使用了接口
    2. 接口就是标准,是用来隔离具体实现的(或者说是和具体实现解耦)
    3. 达到统一访问的目的,因为你实现这个接口的类的方法名相同,但是实现内容不同我用接口来定义对象不就可以做到统一访问。所谓的统一的访问标准其实就是对象不用变,但是访问的权限改变(这个是多态性实现的。)
  2. 抽象类和接口的区别:
    1. 声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。
    2. 接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。
  3. this和super的区别:在Java中,this通常指当前对象,super则指父类的。
    1.this表示指向当前对象的指针,同时也可以调用当前对象的其他构造函数。
    2.super表示指向父类的指针,使用它可以得到父类的属性或者方法。同时,子类的构造函数必须实现父类的构造函数,使用的就是super()或者super(param).

  4. Object类里面定义的线程的方法:
    1.wait()是一个线程处于等待的状态,并且释放所持有的对象的lock(持有lock的对象才可以对资源进行访问!)
    2.sleep()是一个线程进行休眠,时间一到继续运行,这个和wait()是不同的。
    3.notify():唤醒一个正在等待的线程,注意是在调用此方法的时候,并不能确切的唤醒某一个线程,这个是有JVM决定的。

  5. JAVA实现多态的机制是什么?是子类中方法的覆写以及同一个类里面方法的重载。多态有两种,一种是运行时多态,一种是编译时多态。一般来说,运行时多态指的就是重载,因为这时候的方法名称和参数全部一样,所以要使用到绑定技术,,而编译时多态其实就是在编译的时候就可以确定调用哪个方法了。
    JAVA内存详解
    首先,java将对内存的管理直接交给了jvm,也就是它会自动的帮我们进行GC(垃圾回收)而不用我们程序员自己手动的进行GC(c++就要。)但是有时候如果内存溢出出现错误的话,我们还是要自己进行手动的处理。所以理解java内存操所是很有必要的。
    首先,了解什么是JVM,JVM是java虚拟机,为什么java可以实现平台无关?其实JVM扮演的就是一个java程序和操作系统的桥梁,也就说,所有的工作由JVM进行,内存的调度也是JVM完成的。
  6. 栈:保存局部变量的值。这里的局部变量有:1.基本数据类的值 2.保存类的实例(这个类的实例,其实就是对象的引用,Object obj=new Object(),这时候的obj是对象实例,new Object是对象。obj知识一个指向对堆内存的指针)
  7. 堆:用来存动态产生的数据,比如书new出来的新对象(注意区分什么是实例,什么是对象!!new出来的是对象。)注意,此时创建出来的对象只包含了属于各自成员变量,并不包括成员方法,因为同一个类的对象拥有各自的成员变量,存储在各自的堆内存,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。
  8. 常量池:JVM为每个已经加载的类型维护一个常量池。包括(基本数据类型,String)和对其他类型,方法,字段的符号引用。
    其实变量类型,就两种类型的变量:基本类型和引用类型。二者作为局部变量,都放在栈中,基本类型直接在栈中保存值,引用类型只保存一个指向堆区的指针,真正的对象在堆里。作为参数时基本类型就直接传值,引用类型传指针。
    1.分清什么是实例什么是对象。Class a= new Class();此时a叫实例,而不能说a是对象。实例在栈中,对象在堆中,操作实例实际上是通过实例的指针间接操作对象。多个实例可以指向同一个对象。

2.栈中的数据和堆中的数据销毁并不是同步的。方法一旦结束,栈中的局部变量立即销毁,但是堆中对象不一定销毁。因为可能有其他变量也指向了这个对象,直到栈中没有变量指向堆中的对象时,它才销毁,而且还不是马上销毁,要等垃圾回收扫描时才可以被销毁。
3.常量池维护的问题:

public class TestConstant {
public static void main(String[] args) {
    Integer a=40;
    Integer b=40;
    System.out.println(a==b);
    Integer c=400;
    Integer d=400;
    System.out.println(c==d);
  }
  }

第一个输出是true,第二个是false;为什么?常量池维护的常量为-127-127,当你的数据超过127时,是要使用new Integer()创建出一个新的对象的。这当然就不一样了,40之所以一样是因为常量池里面维护着-127-127这范围里面的对象了。这个其实是一个装箱技术实现的,它会判断被装箱的数据是不是在-127-127之间。堆里面-127-127对象只有一个对象,其他实例直接指向它们就可以。2.String类型也实现了常量池技术,但是稍微有点不同。String型是先检测常量池中有没有对应字符串,如果有,则取出来;如果没有,则把当前的添加进去。