Java知识查漏补缺(一)

Java基础知识查漏补缺(一)

  1. 单元测试中,Mock对象的存在破坏了面向对象中的封装

    mock对象:也成为伪对象,在测试中的利用mock对象来代替真实对象,方便测试的进行。

    java的封装性:指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,通过该类提供的方法实现对内部信息的操作访问。

    反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性

  2. transient变量

    java 的transient关键字的作用是需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

  3. Servlet的声明周期

    创建Servlet的实例是由Servlet容器来完成的,且创建Servlet实例是在初始化方法init()之前

    Servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。

    (1)加载:容器通过类加载器使用servlet类对应的文件加载servlet

    (2)创建:通过调用servlet构造函数创建一个servlet对象

    (3)初始化:调用init方法初始化

    (4)处理客户请求:每当有一个客户请求,容器会创建一个线程来处理客户请求

    (5)卸载:调用destroy方法让servlet自己释放其占用的资源

  4. Java使用监视器机制实现了进程之间的同步执行。

    同步的两种方式:同步块和同步方法
    对于同步来说都是使用synchronized方法
    每一个对象都有一个监视器,或者叫做

  5. 序列化问题

    Java在序列化时不会实例化static变量和transient修饰的变量,因为static代表类的成员,transient代表对象的临时数据,被声明这两种类型的数据成员不能被序列化

  6. finally语句块执行问题

    try-catch-finally块中,finally块在以下几种情况将不会执行。

    (1)finally块中发生了异常。

    (2)程序所在线程死亡。

    (3)在前面的代码中用了System.exit();

    (4)关闭了CPU

    :在catch中的return语句不影响finally的执行

  7. return与finally的执行顺序对返回值的影响

    (1)当仅try中含有return时,finally语句块会执行,但finally对return变量的重新赋值修改无效;

    (2)当tryfinally中均含有return语句时,return值以finally语句块中的返回值为准。

  8. 排序算法复杂度问题(最优+最坏+平均,稳定性)

    Java知识查漏补缺(一)

  9. final关键字全面总结

    1.final修饰变量,则等同于常量

    2.final修饰方法中的参数,称为最终参数。

    3.final修饰类,则类不能被继承

    4.final修饰方法,则方法不能被重写。

    5.final 不能修饰抽象类

    6.final修饰的方法可以被重载 但不能被重写

  10. static关键字全面总结

    1.static修饰表示静态或全局,被修饰的属性和方法可以通过类名直接访问

    2.static修饰的代码块表示静态代码块,当JVM加载类时,就会执行且只执行一次

    3.static修饰的属性(变量),在类加载时被创建并进行初始化,只会被创建一次

    4.static修饰的变量可以重新赋值

    5.static方法中不能用this和super关键字

    6.static方法必须被实现,而不能是抽象的abstract

    7.static方法不能被重写

    • final和static的异同

    都可以修饰类、方法、成员变量
    都不能用于修饰构造方法

    static可以修饰类的代码块,final不可以
    final可以修饰方法内的局部变量,而static不可以

    • 在接口中,属性都是默认public static final 修饰的

    不能用private修饰,final修饰的属性必须赋值,三个关键字可以省略

  11. X.equals(9)自动装箱问题

    在执行equals方法前会先对9进行自动装箱,即先调用Integer.valueOf()方法,因为JVM会缓存Integer的[-128,127]范围的数,所以直接返回引用,不会创建新对象

  12. byte和char在c++和Java中的区别

    java中只有byte, boolean是一个字节, char是两个字节,所以127的char类型加1不会溢出

    对于c/c++语言来说, char是一个字节,127的char类型加1会发生溢出

  13. switch判定条件变化

    在Java7之前,switch只能支持 byte、short、char、int或者其对应的封装类以及Enum类型。(因为这些类型都可经过自动拆卸、自动向上转型得到int类型)

    在Java7之后,String类型得到支持,原理:(本质上还是对int类型值的匹配)

    ​ 通过对case后面得String对象调用hashCode方法,得到一个int类型得hash值,然后用这个hash值来唯一标识这个case。那么当匹配时,首先调用exp的hashCode,得到exp的hash值,用这个hash值来匹配所有case,如果没有匹配成功,就说明不存在;如果匹配成功了,接着会调用字符串的equals方法进行匹配。(hash值一致,equals可不一定返回的就是true)。
    所以,exp不能为nullcas子句使用的字符串也不能为null,不然会出现空指针异常。

  14. socket编程中客户端和服务端操作图解

    Java知识查漏补缺(一)

  15. Java初始化过程

    1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;

    2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;

    3.其次,初始化父类的普通成员变量和代码块,在执行父类的构造方法;

    4.最后,初始化子类的普通成员变量和代码块,在执行子类的构造方法;

    题目链接

  16. Java运行时多态题目

    执行对象实例化过程中遵循多态特性 ==> 调用的方法都是将要实例化的子类中的重写方法,只有明确调用了super.xxx关键词或者是子类中没有该方法时,才会去调用父类相同的同名方法。

    题目链接

  17. Java静态分派

    题目链接

    static方法不能被子类覆写,在子类中定义了和父类完全相同的static方法,则父类的static方法被隐藏

    Son.staticmethod()或new Son().staticmethod()都是调用的子类的static方法,Father.staticmethod()或者Father f = new Son(); f.staticmethod()调用的都是父类的static方法。

  18. 面向字符的流

    Java知识查漏补缺(一)

    Java知识查漏补缺(一)

  19. 常用集合类总结

    [注]:Collection有两个子接口:ListSet,二者主要区别在于:list数据有序存放、可重复;set中数据无序存放,不可重复

    • 线程安全的集合对象
      (1)Vector

      ​ 同ArrayList一样使用数组实现,但同一时刻只能有一个线程写,实现同步开销较大,访问速度较ArrayList慢。

      (2)HashTable
      a. 无论是key还是value都不允许有null值的存在;在HashTable中调用Put方法时,如果key为null,直接抛出NullPointerException异常;
      b. 遍历使用的是Enumeration列举;

      ​ c.对整张hash表加锁

      (3)StringBuffer

      (4)ConcurrentHashMap

      ​ 将Hash表分为16桶(segment),每次只对需要的桶加锁

      (5)Collections的SynchronizedXXX方法

      ​ 可以将指定的集合包装成线程同步的集合,如:

      List list = Collections.synchronizedList(new ArrayList());

      Set set = Collections.synchronizedSet(new HashSet());

    • 线程不安全的集合对象

      (1)ArrayList

      ​ a. 当操作是在一列数据的后面添加数据而不是在前面或者中间,并需要随机地访问其中的元素时,使用ArrayList性能比较好。
        b. ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除

      (2)LinkedList

      ​ a. 当对一列数据的前面或者中间执行添加或者删除操作时,并且按照顺序访问其中的元素时,要使用LinkedList。
        b. LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

      (3)HashMap

      ​ a. 采用数组方式存储key-value构成的Entry对象,无容量限制;
      ​ b.基于key hash查找Entry对象存放到数组的位置,对于hash冲突采用链表的方式去解决;
      ​ c. 在插入元素时,可能会扩大数组的容量,在扩大容量时须要重新计算hash,并复制对象到新的数组中;
      ​ d. 遍历使用的是Iterator迭代器;

      (4)HashSet

      ​ a. 基于HashMap实现,无容量限制;
      ​ b. 是非线程安全的;
      ​ c. 不保证数据的有序

      (5)TreeMap

      ​ a. 典型的基于红黑树的Map实现,因此它要求一定要有key比较的方法,要么传入Comparator比较器实现,要么key对象实现Comparator接口;
      ​ b. 是非线程安全的;

      (6)TreeSet

      ​ a. 基于TreeMap实现的,支持排序;
      ​ b. 是非线程安全的

      (7)StringBuilder

    • ArrayList和LinkedList,Vector的比较

      (1)性能上

      ​ ArrayList底层数据结构是数组,适合随机查找和遍历,不适合插入和删除,线程不安全,效率高。LinkedList底层数据结构是链表, 适合数据的动态插入和删除,随机访问和遍历速度比较慢,线程不安全,效率高。Vector实现了线程安全,但开销较大,访问速度较ArrayList慢。

      (2)同步性上

      ​ Vectors是可同步的,是线程安全的。ArrayList是不可同步的,不是线程安全的。所以,一般单线程推荐用ArrayList,多线程中则用Vector 。

      (3)数据增长

      ​ 往一个ArrayList或者Vector里插入一个元素时,如果内部数组空间不够,ArrayList或Vector会扩展它的大小。Vector在默认情况下增长一倍的大小,而ArrayList会增加50%的大小

  20. Java类加载器

    类的加载是由类加载器完成的,类加载器包括:根加载器( BootStrap )扩展加载器( Extension )系统加载器( System )用户自定义类加载器( java.lang.ClassLoader 的子类)。从 Java 2 ( JDK 1.2 )开始,类加载过程采取了父亲委托机制( PDM )。 PDM 更好的保证了 Java 平台的安全性,在该机制中, JVM 自带的 Bootstrap 是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。 JVM 不会向 Java 程序提供对 Bootstrap 的引用。下面是关于几个类加载器的说明:

    • Bootstrap :一般用本地代码实现,负责加载 JVM 基础核心类库( rt.jar )
    • Extension :从 java.ext.dirs 系统属性所指定的目录中加载扩展类库,它的父加载器是 Bootstrap ;
    • system class loader :又叫应用类加载器,其父类是 Extension 。它是应用最广泛的类加载器。它从环境变量 classpath 或者系统属性 java.class.path 所指定的目录中加载类,是用户自定义加载器的默认父加载器。
    • 用户自定义类加载器: java.lang.ClassLoader 的子类
  21. Java中的类型转换

    • 自动类型转换(隐式转换)

    数值型数据的转换:byte→short→int→long→float→double。
    字符型转换为整型:char→int。

    注意:表达式中类型的自动提升,自动向上转型

    但有些时候自动类型提升会发生问题,如:

    byte b = 50;

    b = b * 2;//会发出类型不匹配的错误,提示无法从int转为byte

    这是由于,在b*2的时候自动进行了类型提升,转为int类型,如果要保证结果为byte则需要强转

    b=(byte)(b*2);

    注意:char 类型比较特殊,char 自动转换成 int、long、float 和 double,但 byte 和 short 不能自动转换为 char,而且 char 也不能自动转换为 byte 或 short。

    • 强制类型转换(显式转换)

      TarType t = (TarType)SrcType;

  22. WEB开发中的会话跟踪技术

    会话跟踪是一种灵活、轻便的机制,它使Web上的状态编程变为可能。
    HTTP是一种无状态协议,每当用户发出请求时,服务器就会做出响应,客户端与服务器之间的联系是离散的、非连续的。当用户在同一网站的多个页面之间转换时,根本无法确定是否是同一个客户,会话跟踪技术就可以解决这个问题。当一个客户在多个页面间切换时,服务器会保存该用户的信息。
    有四种方法可以实现会话跟踪技术:URL重写、隐藏表单域、Cookie、Session
    1)隐藏表单域:,非常适合步需要大量数据存储的会话应用。
    2)URL 重写:URL 可以在后面附加参数,和服务器的请求一起发送,这些参数为名字/值对。
    3)Cookie:一个 Cookie 是一个小的,已命名数据元素。服务器使用 SET-Cookie 头标将它作为 HTTP
    响应的一部分传送到客户端,客户端被请求保存 Cookie 值,在对同一服务器的后续请求使用一个
    Cookie 头标将之返回到服务器。与其它技术比较,Cookie 的一个优点是在浏览器会话结束后,甚至
    在客户端计算机重启后它仍可以保留其值
    4)Session:使用 setAttribute(String str,Object obj)方法将对象捆绑到一个会话

  23. JavaWeb中的监听器

    三类八种(ServletContext,HttpSession,ServletRequest)

    1. 监听三个域对象的创建销毁的监听器:
      * ServletContextListener
      * HttpSessionListener
      * ServletRequestListener

    2. 监听三个域对象的属性变更的监听器(属性添加,移除,替换):
      * ServletContextAttributeListener
      * HttpSessionAttributeListener
      * ServletRequestAttributeListener

    3. 监听HttpSession中的JavaBean的状态改变(绑定,解除绑定,钝化,活化)

      * HttpSessionBindingListener
      * HttpSessionActivationListene

  24. Java类的种类

    (a)内嵌于Web页中,由浏览器来观看的Applet

    (b)可独立运行的 Application

    (c)服务器端的 Servlet