Java面试常见知识点总结(三)

21.volatile关键字:

   一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰以后,那么就具有了两层语义:
   (1) 保证了不一样线程对这个变量进行操做时的可见性,即一个线程修改了某个变量的值,这新值对其余线程来讲是当即可见的。
   (2) 禁止进行指令重排序。
       volatile只提供了保证访问该变量时,每次都是从内存中读取最新值,并不会使用寄存器缓存该值—每次都会从内存中读取。
       而对该变量的修改,volatile并不提供原子性的保证
       因为及时更新,极可能致使另外一线程访问最新变量值,没法跳出循环的状况, 多线程下计数器必须使用锁保护程序员

22.super和this关键字:

    (1) 调用super()必须写在子类构造方法的第一行,不然编译不经过。每一个子类构造方法的第一条语句,都是隐含地调用super(),若是父类没有这种形式的构造函数,那么在编译的时候就会报错。
    (2) super()和this()相似, 区别是: super从子类中调用父类的构造方法,this()在同一类内调用其它方法。
    (3) super()和this()均需放在构造方法内第一行
    (4) 尽管能够用this调用一个构造器,但却不能调用两个
    (5) this和super不能同时出如今一个构造函数里面,由于this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,因此在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会经过。
    (6) this()和super()都指的是对象,因此,均不能够在static环境中使用。包括:static变量, static方法,static语句块。
    (7) 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字web

23.OuterClass类:

    1) 为何使用内部类?
    使用内部类最吸引人的缘由是:每一个内部类都能独立地继承一个(接口的)实现,因此不管外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
    使用内部类最大的优势就在于它可以很是好的解决多重继承的问题,使用内部类还可以为咱们带来以下特性:
      (1) 内部类能够用多个实例,每一个实例都有本身的状态信息,而且与其余外围对象的信息相互独。
      (2) 在单个外围类中,可让多个内部类以不一样的方式实现同一个接口,或者继承同一个类。
      (3) 建立内部类对象的时刻并不依赖于外围类对象的建立。
      (4) 内部类并无使人迷惑的“is-a”关系,他就是一个独立的实体。
      (5) 内部类提供了更好的封装,除了该外围类,其余类都不能访问。
    2) 内部类分类:
    (一) 成员内部类:
     (1) Inner 类定义在 Outer 类的内部,至关于 Outer 类的一个成员变量的位置,Inner 类可使用任意访问控制符,如 public 、 protected 、 private 等。
     (2) Inner 类中定义的 show() 方法能够直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer 类中的私有属性age。
     (3) 定义了成员内部类后,必须使用外部类对象来建立内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( );
     (4) 编译上面的程序后,会发现产生了两个.class 文件: Outer.class,Outer$Inner.class{}。
     (5) 成员内部类中不能存在任何static 的变量和方法, 能够定义常量:
        ● 由于非静态内部类是要依赖于外部类的实例,而静态变量和方法是不依赖于对象的,仅与类相关, 简而言之:在加载静态域时,根本没有外部类,所在在非静态内部类中不能定义静态域或方法,编译不经过; 非静态内部类的做用域是实例级别。
        ● 常量是在编译器就肯定的, 放到所谓的常量池了。
    ★ 外部类是不能直接使用内部类的成员和方法的,可先建立内部类的对象,而后经过内部类的对象来访问其成员变量和方法;
    ★ 若是外部类和内部类具备相同的成员变量或方法,内部类默认访问本身的成员变量或方法,若是要访问外部类的成员变量,可使用 this 关键字,如:Outer.this.name。
   (二) 静态内部类: 是 static 修饰的内部类
    (1) 静态内部类不能直接访问外部类的非静态成员,但能够经过 new 外部类().成员 的方式访问
    (2) 若是外部类的静态成员与内部类的成员名称相同,可经过“类名.静态成员”访问外部类的静态成员;若是外部类的静态成员与内部类的成员名称不相同,则可经过“成员名”直接调用外部类的静态成员。
    (3) 建立静态内部类的对象时,不须要外部类的对象,能够直接建立 内部类 对象名 = new 内部类()。
   (三) 方法内部类:访问仅限于方法内或者该做用域内
    (1) 局部内部类就像是方法里面的一个局部变量同样,是不能有 public、protected、private 以及 static 修饰符的。
    (2) 只能访问方法中定义的 final 类型的局部变量, 由于: 当方法被调用运行完毕以后,局部变量就已消亡了。但内部类对象可能还存在, 直到没有被引用时才会消亡。此时就会出现一种状况,就是内部类要访问一个不存在的局部变量; 使用final修饰符不只会保持对象的引用不会改变,并且编译器还会持续维护这个对象在回调方法中的生命周期. 局部内部类并非直接调用方法传进来的参数,而是内部类将传进来的参数经过本身的构造器备份到了本身的内部,本身内部的方法调用的实际是本身的属性而不是外部类方法的参数; 防止被篡改数据,而致使内部类获得的值不一致。在内部类中的属性和外部方法的参数二者从外表上看是同一个东西,但实际上却不是,因此他们二者是能够任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,若是内部类该变了,而外部方法的形参却没有改变,这是难以理解和不可接受的,因此为了保持参数的一致性,就规定使用 final来避免形参的不改变。
   (四) 匿名内部类:
    (1) 匿名内部类是直接使用 new 来生成一个对象的引用;
    (2) 对于匿名内部类的使用它是存在一个缺陷的,就是它仅能被使用一次,建立匿名内部类时它会当即建立一个该类的实例,该类的定义会当即消失,因此匿名内部类是不可以被重复使用;
    (3) 使用匿名内部类时,咱们必须是继承一个类或者实现一个接口,可是二者不可兼得,同时也只能继承一个类或者实现一个接口;
    (4) 匿名内部类中是不能定义构造函数的,匿名内部类中不能存在任何的静态成员变量和静态方法;
    (5) 匿名内部类中不能存在任何的静态成员变量和静态方法,匿名内部类不能是抽象的,它必需要实现继承的类或者实现的接口的全部抽象方法;
    (6) 匿名内部类初始化:使用构造代码块!利用构造代码块可以达到为匿名内部类建立一个构造器的效果。缓存

24.Spring的事务传播特性:

    PROPAGATION_REQUIRED--支持当前事务,若是当前没有事务,就新建一个事务。这是最多见的选择。
    PROPAGATION_SUPPORTS--支持当前事务,若是当前没有事务,就以非事务方式执行。
    PROPAGATION_MANDATORY--支持当前事务,若是当前没有事务,就抛出异常
    PROPAGATION_REQUIRES_NEW--新建事务,若是当前存在事务,把当前事务挂起
    PROPAGATION_NOT_SUPPORTED--以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。
    PROPAGATION_NEVER--以非事务方式执行,若是当前存在事务,则抛出异常多线程

25.Servlet的生命周期:

    Servlet的生命周期分为5个阶段:加载建立初始化处理客户请求卸载
    (1) 加载:容器经过类加载器使用servlet类对应的文件加载servlet。
    (2) 建立:经过调用servlet构造函数建立一个servlet对象。
    (3) 初始化:调用init方法初始化。
    (4) 处理客户请求:每当有一个客户请求,容器会建立一个线程来处理客户请求。
    (5) 卸载:调用destroy方法让servlet本身释放其占用的资源。app

26.Java反射机制:

    Java反射机制概念:Java反射机制是在运行状态中,对于任意一个,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
    Java反射机制主要提供了如下功能:
     (1) 在运行时判断任意一个对象所属的类
     (2) 在运行时构造任意一个类的对象
     (3) 在运行时判断任意一个类所具备的成员变量和方法
     (4) 在运行时调用任意一个对象的方法
     (5) 生成动态代理框架

27.Struts:

    Struts的工做流程: 在web应用启动时就会加载初始化ActionServlet, ActionServlet从struts-config.xml文件中读取配置信息, 把它们存放到各类配置对象, 当ActionServlet接收到一个客户请求时, 将执行以下流程.
    (1) 检索和用户请求匹配的ActionMapping实例, 若是不存在, 就返回请求路径无效信息;
    (2) 若是ActionForm实例不存在, 就建立一个ActionForm对象, 把客户提交的表单数据保存到ActionForm对象中;
    (3) 根据配置信息决定是否须要表单验证. 若是须要验证, 就调用ActionForm的validate()方法;
    (4) 若是ActionForm的validate()方法返回或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功;
    (5) ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪一个Action, 若是相应的Action实例不存在, 就先建立这个实例, 而后调用Action的execute()方法;
    (6) Action的execute()方法返回一个ActionForward对象, ActionServlet在把客户请求转发给ActionForward对象指向的JSP组件;
    (7) ActionForward对象指向JSP组件生成动态网页, 返回给客户;
   为何要用Struts?
    JSP、Servlet、JavaBean技术的出现给咱们构建强大的企业应用系统提供了可能。但用这些技术构建的系统很是的繁乱,因此在此之上,咱们须要一个规则、一个把这些技术组织起来的规则,这就是框架,Struts便应运而生。 基于Struts开发的应用由3类组件构成:控制器组件、模型组件、视图组件(MVC)。jvm

28.堆(heap)栈(stack)的区别?

   1) JAVA的JVM的内存:函数

    堆区:
    (1) 存储的所有是对象, 每一个对象都包含一个与之对应的class的信息。(class的目的是获得操做指令) .
    (2) jvm只有一个堆区(heap)被全部线程共享,堆中不存放基本类型和对象引用,只存放对象自己.
   栈区:
    (1) 每一个线程包含一个栈区,栈中只保存基础数据类型的对象自定义对象的引用(不是对象),对象都存放在堆区中.
    (2) 每一个栈中的数据(原始类型和对象引用)都是私有的, 其余栈不能访问. 
    (3) 栈分为3个部分:基本类型变量区、执行环境上下文、操做指令区(存放操做指令).ui

   2) 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不一样,Java自动管理栈和堆, 程序员不能直接地设置栈或堆。
   3) 栈的优点是, 存取速度比堆要快, 仅次于直接位于CPU中的寄存器。但缺点是, 存在栈中的数据大小与生存期必须是肯定的, 缺少灵活性。另外, 栈数据能够共享。堆的优点是能够动态地分配内存大小,生存期也没必要事先告诉编译器,Java的垃圾收集器会自动收走这些再也不使用的数据。但缺点是,因为要在运行时动态分配内存,存取速度较慢this

   4) 在C语言里堆(heap)和栈(stack)里的区别:

     heap:是由malloc之类函数分配的空间所在地。地址是由低向高增加的。
     stack:是自动分配变量,以及函数调用的时候所使用的一些空间。地址是由高向低减小。 

    (1) 管理方式不一样:栈(stack)由编译器管理;堆(heap)由程序员管理。 
    (2) 空间大小不一样:win32中,堆(heap)可达4G;VC中栈默认1M(能够修改)。 
    (3) 碎片问题:堆(heap)易产生;栈(stack)不会。 
    (4) 生长方向不一样:堆(heap)生长方向是向上的,也就是向着内存增长的方向;栈(stack)相反。 
    (5) 分配方式不一样:堆(heap)是动态的,没有静态的堆;栈(stack)有两种:动态和静态。 
    (6) 分配效率不一样:栈(stack),系统提供底层支持,有专门的寄存器存放栈地址,效率高;堆(heap),由库函数提供支持,效率底。  

相关文章
相关标签/搜索