牛客网Java面试常考知识点总结

  1. 字符串间比较:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class Demo {
    public static void main(String args[]) {
    String str1 = new String("hello");
    String str2 = new String("hello");
    String str3 = "hello";
    String str4 = "hello";
    String str5 = "he"+"llo";
    String str6 = "he";
    String str7 = "llo";
    System.out.println(str1==str2);
    System.out.println(str1==str3);
    System.out.println(str3==str4);
    System.out.println(str3=="hello");
    System.out.println(str4==(str6+str7));
    }
    }

上面代码的输出结果是:false false true true false

String str1 = new String("hello");这种方式创建的字符串,和正常创建对象一样,保存在堆区。

String str3 = "hello";这种方式创建的字符串,保存在字符串常量区。

  1. CGI(Common Gateway Interface)和servlet 的总结与对比:

    1. CGI: 主要用Perl、Shell Script或C编写
      Servlet:用java语言编写
    2. CGI:每个请求都会启动一个新的进程,每个进程只为一个客户所服务,导致服务器内存和cpu开销大。
      Servlet:每个请求会产生新的线程,而不是进程,减少系统中进程数量,并发处理能力强。多个客户能在同一个进程中的同时得到服务。
    3. CGI进程在服务完成后就被销毁,所以效率上低于servlet。
      Servlet进程(实例)处于服务器进程中,只有在服务器被卸载时才会被卸载。
    4. CGI是不可移植的,是运行于特定平台上的。
      Servlet是可移植的,运行于JVM上的。
  2. 基本类型与包装类型的比较:

    1. 基本型和基本型封装型进行“==”运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;
    2. 两个Integer类型进行“==”比较,如果其值在-128至127,那么返回true,否则返回false, 这跟Integer.valueOf()的缓冲对象有关,这里不进行赘述。
    3. 两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true
    4. 基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行3中的比较
  3. 一个文件中,可以有多个public class。一个类中可以有两个main方法。

  4. 集合中线程安全的类有:vector,stack,hashtable,enumeration,除此之外均是非线程安全的类与接口
  5. HashTable和HashMap区别:
    1. 继承不同。 public class Hashtable extends Dictionary implements Map public class HashMap extends AbstractMap implements Map
    2. Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。
    3. Hashtable中,key和value都不允许出现null值。 在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
    4. 两个遍历方式的内部实现上不同。 Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
    5. 哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
    6. Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
  6. 引用类型只有String可以直接赋值,其他的都要new出来。
  7. 成员内部类前面可以修饰public,protected和private;可以把局部内部类当做一个局部变量,所以它是不需要加任何修饰符的。局部内部类前不能用修饰符public和private,protected,内部类就随意了。
  8. 如果finally块中有return语句的话,它将覆盖掉函数中其他return语句。
  9. <<表示左移位 >>表示带符号右移位;>>>表示无符号右移;但是没有<<<运算符
  10. exception是JSP九大内置对象之一,其实例代表其他页面的异常和错误。只有当页面是错误处理页面时,即isErroePage为 true时,该对象才可以使用。
  11. LinkedBlockingQueue是一个可选有界队列,不允许null值;PriorityQueue是一个无界队列,不允许null值,入队和出队的时间复杂度是O(log(n));LinkedBlockingQueue是线程安全的;PriorityQueue底层实现是小根堆,不是FIFO的;
  12. 对于局部内部类,只有在方法的局部变量被标记为final或局部变量是effctively final的,内部类才能使用它们;成员内部类位于外部类内部,可以直接调用外部类的所有方法(静态方法和非静态方法);匿名内部类用法与局部内部类不一致,首先从定义上就不一样,匿名类用在任何允许存在表达式的地方,而局部内部类用于在任何允许出现局部变量的地方出现。还有更重要的是匿名类只能使用一次,而局部类则可以在自己的定义域内多次使用;静态内部类不能直接访问外部类的非静态成员,但可以通过new外部类().成员的方式访问。
  13. 类中实例变量可以不用初始化,使用相应类型的默认值即可;方法中的定义的局部变量必须初始化,否则编译不通过。
  14. sleep和wait的区别有:
    1. 这两个方法来自不同的类分别是Thread和Object
    2. 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得敏感词线程可以使用同步控制块或者方法。
    3. wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
      synchronized(x){
      x.notify()
      //或者wait()
      }
    4. sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
  15. 类中的成员变量,存放在堆区;局部变量,存放在栈区.
  16. super.getClass().getName();//返回:包名+类名
  17. Java中的byte,short,char进行计算时都会提升为int类型。而声明为final的变量会被JVM优化。
  18. jre 判断程序是否执行结束的标准是所有的前台线程执行完毕。使用Thread建立的线程默认情况下是前台线程,在进程中,只要有一个前台线程未退出,进程就不会终止。主线程就是一个前台线程。而后台线程不管线程是否结束,只要所有的前台线程都退出(包括正常退出和异常退出)后,进程就会自动终止。
  19. 集合框架中线程安全的类:喂(Vector)S(Stack)H(hashtable)E(enumeration)。
  20. 列表(List)的元素是有 序、可重复的;集合(Set)的元素是无序、不可重复的。
  21. 非运行异常=检查异常 需要try catch捕获或者throws抛出。
  22. 栈区:存放函数的参数、局部变量等;堆区:存放对象;全局区(静态区):存放全局变量和静态变量;常量区:存放常量字符串;代码区:存放函数体的二进制代码。
  23. const和goto是保留字。
  24. return i++, 先返回i,然后i+1。
  25. Java8的接口方法可以有如下定义:only public, abstract, default, static and strictfp are permitted
  26. ArrayList删除元素后,剩余元素会依次向前移动,因此下标一直在变,size()也会减小;
  27. StringBuffer s = new StringBuffer(x); x为初始化容量长度
  28. HashTable与HashMap:
    1. HashMap和Hashtable两个类都实现了Map接口,二者保存K-V对(key-value对)
    2. HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。
    3. Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
    4. 由所有HashMap类的“collection 视图方法”所返回的迭代器都是快速失败的:在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出ConcurrentModificationException。Hashtable和HashMap的区别主要是前者是同步的,后者是快速失败机制保证.
  29. java对于String类型的相加是通过StringBuffer实现的,先构造一个StringBuffer对象来存放tao,然后通过append方法追加上bao。StringBuffer对象的分配是在堆上的。
  30. java object默认的基本方法中没有copy(),含有如下方法:
    getClass(), hashCode(), equals(), clone(), toString(), notify(), notifyAll(), wait(), finalize().
  31. 程序运行时异常由Java虚拟机自动进行处理.
  32. super是java提供的一个关键字,super用于限定该对象调用它从父类继承得到的Field或方法。super关键字不能出现在static修饰的方法中,因为static修饰的方法是属于类的。如果在构造器中使用super,则super用于限定该构造器初始化的是该对象从父类继承得到的field,而不是该类自己定义的field。需要注意的是,super关键字只能指代直接父类,不能指代父类的父类。
  33. str1指向常量池中的字符串;str2是通过StringBuilder类new出的对象,指向堆。故为false.

    1
    2
    3
    String str1 = "hello";
    String str2 = "he" + new String("llo");
    System.err.println(str1 == str2);
  34. 父类静态代码块–>子类静态代码块–>父类普通代码块–>父类构造方法–>子类代码块–>子类构造方法;

  35. ResultSet跟普通的数组不同,索引从1开始而不是从0开始.
  36. 接口与抽象类:接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。另外,接口和抽象类在方法上有区别:
    1. 抽象类可以有构造方法,接口中不能有构造方法。
    2. 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
    3. 抽象类中可以有普通成员变量,接口中没有普通成员变量
    4. 抽象类中的抽象方法的访问类型可以是public,protected和默认类型
    5. 抽象类中可以包含静态方法,接口中不能包含静态方法
    6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型
    7. 一个类可以实现多个接口,但只能继承一个抽象类。二者在应用方面也有一定的区别:接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,可以实现代码的重用,例如,模板方法设计模式是抽象类的一个典型应用,假设某个项目的所有Servlet类都要用相同的方式进行权限判断、记录访问日志和处理异常,那么就可以定义一个抽象的基类,让所有的Servlet都继承这个抽象基类,在抽象基类的service方法中完成权限判断、记录访问日志和处理异常的代码,在各个子类中只是完成各自的业务逻辑代码。
  37. Java标识符由数字、字母、下划线(_)、美元符号($)或人民币(¥)组成,首位不能是数字。并且Java关键字不能作为标识符。
  38. 会话跟踪是一种灵活、轻便的机制,它使Web上的状态编程变为可能。HTTP是一种无状态协议,每当用户发出请求时,服务器就会做出响应,客户端与服务器之间的联系是离散的、非连续的。当用户在同一网站的多个页面之间转换时,根本无法确定是否是同一个客户,会话跟踪技术就可以解决这个问题。当一个客户在多个页面间切换时,服务器会保存该用户的信息。有四种方法可以实现会话跟踪技术:URL重写、隐藏表单域、Cookie、Session。
  39. JDBC提供了Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程;对于PreparedStatement来说,数据库可以使用已经编译过及定义好的执行计划,由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象”;
  40. HttpServletResponse完成:设置http头标,设置cookie,设置返回数据类型,输出返回数据;
  41. 抛出一个异常时可以终止当前线程的运行.
  42. ThreadLocal类用于创建一个线程本地变量
    在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值为就是变量的副本。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。
    ThreadLocal的使用场景:数据库连接:在多线程中,如果使用懒汉式的单例模式创建Connection对象,由于该对象是共享的,那么必须要使用同步方法保证线程安全,这样当一个线程在连接数据库时,那么另外一个线程只能等待。这样就造成性能降低。如果改为哪里要连接数据库就来进行连接,那么就会频繁的对数据库进行连接,性能还是不高。这时使用ThreadLocal就可以既可以保证线程安全又可以让性能不会太低。但是ThreadLocal的缺点时占用了较多的空间。
  43. 泛型:
    1. 只看尖括号里边的!!明确点和范围两个概念
    2. 如果尖括号里的是一个类,那么尖括号里的就是一个点,比如List<A>,List<B>,List<Object>
    3. 如果尖括号里面带有问号,那么代表一个范围,<? extends A> 代表小于等于A的范围,<? super A>代表大于等于A的范围,<?>代表全部范围
    4. 尖括号里的所有点之间互相赋值都是错,除非是俩相同的点
    5. 尖括号小范围赋值给大范围,对,大范围赋值给小范围,错。如果某点包含在某个范围里,那么可以赋值,否则,不能赋值
    6. List<?>和List是相等的,都代表最大范围;
    7. 补充:List既是点也是范围,当表示范围时,表示最大范围
  44. 服务器端通过new ServerSocket()创建TCP连接对象;服务器端通过TCP连接对象调用accept()方法创建通信的Socket对象;客户端通过new Socket()方法创建通信的Socket对象。
  45. Java中类是单继承,但接口可以多继承,Interfere1 extends Interface2,Interface3…
  46. 方法区在JVM中也是一个非常重要的区域,它与堆一样,是被 线程共享 的区域。 在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
  47. 大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟机栈,也有翻译成JAVA 方法栈的),Native Method Stack ( 本地方法栈 ),其中Method Area 和 Heap 是线程共享的 ,VM Stack,Native Method Stack 和Program Counter Register 是非线程共享的。为什么分为 线程共享和非线程共享的呢?请继续往下看。首先我们熟悉一下一个一般性的 Java 程序的工作过程。一个 Java 源程序文件,会被编译为字节码文件(以 class 为扩展名),每个java程序都需要运行在自己的JVM上,然后告知 JVM 程序的运行入口,再被 JVM 通过字节码解释器加载运行。那么程序开始运行后,都是如何涉及到各内存区域的呢?概括地说来,JVM初始运行的时候都会分配好 Method Area(方法区) 和Heap(堆) ,而JVM 每遇到一个线程,就为其分配一个 Program Counter Register(程序计数器) , VM Stack(虚拟机栈)和Native Method Stack (本地方法栈), 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为什么我把内存区域分为线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也是系统垃圾回收的场所只发生在线程共享的区域(实际上对大部分虚拟机来说知发生在Heap上)的原因。
  48. 所谓 volatile的措施,就是:
    1. 每次从内存中取值,不从缓存中什么的拿值。这就保证了用 volatile修饰的共享变量,每次的更新对于其他线程都是可见的。
    2. volatile保证了其他线程的立即可见性,就没有保证原子性。
    3. 由于有些时候对 volatile的操作,不会被保存,说明不会造成阻塞。
  49. hashcode和equals的约定关系如下:
    1. 如果两个对象相等,那么他们一定有相同的哈希值(hash code)。
    2. 如果两个对象的哈希值相等,那么这两个对象有可能相等也有可能不相等。(需要再通过equals来判断)
  50. private方法是可以继承的,只是不能调用.
  51. ArrayList的底层是数组,数组通过索引可以快速查找,但是增删都要移动元素的位置,所以增删效率低。LinkedList底层是链表,链表查找只能顺序查找,不能随机查找,所以查找的效率低;
  52. 真数组: 数组元素在内存中是一个接着一个线性存放的,通过第一个元素就能访问随后的元素,避免了数据覆盖的可能性.
  53. 造成Full GC的原因:
    1. 年老代被写满
    2. 持久代被写满
    3. 显示调用System.GC
    4. 上一个GC后个heap的各域分配策略动态变化。
  54. 构造方法每次都是构造出新的对象,不存在多个线程同时读写同一对象中的属性的问题,所以不需要同步 。
  55. 如果父类中的某个方法使用了 synchronized关键字,而子类中也覆盖了这个方法,默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上 synchronized关键字才可。
  56. Java表达式转型规则由低到高转换:
    1. 所有的byte,short,char型的值将被提升为int型;
    2. 如果有一个操作数是long型,计算结果是long型;
    3. 如果有一个操作数是float型,计算结果是float型;
    4. 如果有一个操作数是double型,计算结果是double型;
    5. 被fianl修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转化。
  57. 运行时异常 包括:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。 运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
    非运行时异常(编译异常) 包括:RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常
  58. int i = 0; i = i++;什么都没做。
  59. 两个数值进行二元操作时,会有如下的转换操作:
    如果两个操作数其中有一个是double类型,另一个操作就会转换为double类型。
    否则,如果其中一个操作数是float类型,另一个将会转换为float类型。
    否则,如果其中一个操作数是long类型,另一个会转换为long类型。
    否则,两个操作数都转换为int类型。
  60. 假设利用 return 语句从 try 语句块中退出。在方法返回前,finally子句的内容将被执行。
  61. join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。
  62. 父类没有无参的构造函数,所以子类需要在自己的构造函数中显式调用父类的构造函数。
  63. 静态语句块中x为局部变量,不影响静态变量x的值。
  64. System是java.lang包下的一个类,out为System的final静态成员(PrintStream类型),println()是PrintStream类的实例方法。
  65. 抽象类有构造方法,但是不能new一个对象。
  66. String(大姐,出生于JDK1.0时代) 不可变字符序列 <StringBuffer(二姐,出生于JDK1.0时代) 线程安全的可变字符序列 <StringBuilder(小妹,出生于JDK1.5时代) 非线程安全的可变字符序列。
  67. 转发与重定向(302):
    1. 从地址栏显示来说
      forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
      redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
    2. 从数据共享来说
      forward:转发页面和转发到的页面可以共享request里面的数据.
      redirect:不能共享数据.
    3. 从运用地方来说
      forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
      redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.
    4. 从效率来说
      forward:高.
      redirect:低.
  68. 抽象类的方法可以是public protected的,接口的方法只能是public的.
  69. wait必须捕获异常 并且需要用当前synchronized锁对象进行调用.
  70. 管道实际上是一种固定大小的缓冲区,管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在于内存中。它类似于通信中半双工信道的进程通信机制,一个管道可以实现双向 的数据传输,而同一个时刻只能最多有一个方向的传输,不能两个方向同时进行。管道的容 量大小通常为内存上的一页,它的大小并不是受磁盘容量大小的限制。当管道满时,进程在 写管道会被阻塞,而当管道空时,进程读管道会被阻塞。
  71. 重写接口中的方法,访问权限一定是public。
  72. JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。
  73. 基本数据类型,比较的时候比较的是数值、
  74. 对该数据加锁,放在同步代码块中。
  75. 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或OS环境。
    (简单来说,中间件并不能提高内核的效率,一般只是负责网络信息的分发处理)
  76. Struts1和2的区别:
    Struts1和Struts2的区别和对比:
    Action 类:
  • Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口,而struts2的Action是接口。
  • Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去 实现 常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。
    线程模式:
  • Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
  • Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
    Servlet 依赖:
  • Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
  • Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
    可测性:
  • 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
  • Struts 2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
    捕获输入:
  • Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。
  • Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。
    表达式语言:
  • Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
  • Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--”Object Graph Notation Language” (OGNL).
  1. 创建Servlet的实例是由Servlet容器来完成的,且创建Servlet实例是在初始化方法init()之前。
  2. 枚举类 所有的枚举值都是类静态常量,在初始化时会对所有的枚举值对象进行第一次初始化。
  3. JDK中提供的java、javac、jar等开发工具也是用Java编写的。底层实现c语言。
  4. 创建Statement是不传参的,PreparedStatement是需要传入sql语句。
  5. 父类静态域——》子类静态域——》父类成员初始化——》父类构造块——》父类构造方法——》子类成员初始化——》子类构造块——》子类构造方法
  6. 淡云一笔安洛三福 单目>算数运算符>移位>比较>按位>逻辑>三目>赋值
  7. 两个最基本的java回收算法:复制算法和标记清理算法
    复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
    标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出
    标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
    两个概念:新生代和年老代
    新生代:初始对象,生命周期短的
    永久代:长时间存在的对象
    整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
    P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
    Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
    Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
    Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
    Parallel Old(并行)收集器,针对老年代,标记整理
    CMS收集器,基于标记清理
    G1收集器:整体上是基于标记 整理 ,局部采用复制
    综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。
  8. DBMS中事务有四个特性,持久性,一致性,原子性,隔离性,持久性实现恢复管理子系统,一致性实现并发控制子系统,原子性实现完整性管理子系统,隔离性实现安全控制管理子系统.
  9. 抽象类指有abstract修饰的class,其可以包含抽象方法,也可以不包含.
  10. Java程序的种类有:
    (a)内嵌于Web文件中,由浏览器来观看的_Applet
    (b)可独立运行的 Application
    (c)服务器端的 Servlets
  11. 依赖注入的动机就是减少组件之间的耦合度,使开发更为简洁.
  12. 接口中的成员变量:
    为什么是public:因为接口必然是要被实现的,如果不是public,这个属性就没有意义了;
    为什么是static:因为如果不是static,那么由于每个类可以继承多个接口,那就会出现重名的情况;
    为什么是final:这是为了体现java的开闭原则,因为接口是一种模板,既然是模板,那就对修改关闭,对扩展开放。
  13. finally块中的内容会先于try中的return语句执行,如果finall语句块中也有return语句的话,那么直接从finally中返回了,但是不建议在finally中return。
  14. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的 resume() 被调用,才能使得线程重新进入可执行状态.
  15. 抛InterruptedException的代表方法有:
    java.lang.Object 类的 wait 方法
    java.lang.Thread 类的 sleep 方法
    java.lang.Thread 类的 join 方法
  16. 动态include和静态include区别:
    静态的include:是jsp的指令来实现的,<% @ include file=”xx.html”%> 特点是 共享request请求域,先包含再编译,不检查包含页面的变化。
    动态的include:是jsp动作来实现的,<jsp:include page=”xx.jsp” flush=”true”/> 这个是不共享request请求域,先编译在包含,是要检查包含页面的变化的。
  17. 并不是静态块最先初始化,而是静态域.(BM:啊!多么痛的领悟!)
    而静态域中包含静态变量、静态块和静态方法,其中需要初始化的是静态变量和静态块.而他们两个的初始化顺序是靠他们俩的位置决定的!
  18. 静态变量和静态代码块的执行顺序就是代码前后的顺序。
  19. 在jdk1.8之前声明抽象方法不可写出大括号。
  20. java 虚拟机,对于方法的调用采用的是栈帧(方法调用和方法执行),调用则入栈,完成之后则出栈。不就回收了内存资源而针对于其他,GC回收的时间不定。
  21. byte<char<short<int<long<float<double
  22. Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。
    在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
    堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。
    引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候(比如先前的引用变量x=null时),才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因。
    总结起来就是对象存储在堆内存,引用变量存储在栈内存。栈内存指向堆内存。
  23. java继承中对构造函数是不继承的,只是显式或者隐式调用。
  24. 默认ArrayList的长度是10个。
  25. 导包只可以导到当前层,不可以再导入包里面的包中的类。
  26. java 1.8开始支持接口中定义静态方法。
  27. 堆区:只存放类对象,线程共享;
    方法区:又叫静态存储区,存放class文件和静态数据,线程共享;
    栈区:存放方法局部变量,基本类型变量区、执行环境上下文、操作指令区,线程不共享;
  28. public Method[] getDeclaredMethods()返回类或接口声明的所有方法,包括public, protected, default (package) 访问和private方法的Method对象,但不包括继承的方法。当然也包括它所实现接口的方法。
  29. SimpleDateFormat是线程不安全的。
  30. 截止JDK1.8版本,java并发框架支持锁包括读写锁,自旋锁,乐观锁。
  31. Hibernate鼓励使用双向一对多关联,不使用单向一对多关联。单向一对多关联映射是在one端维护关系的,必须先保存many端后才可以保存one端,所以在保存many端时该端不知道one端是否存在相应的数据,所以只能将维护的关系字段设置为null,如果为非空则无法保存。因为是one端维护关系,所以在保存one端时,会发出多余的update语句维护many端的外键关系。
  32. 在jvm中 是使用监视器锁来实现不同线程的异步执行,在语法的表现就是synchronized 。
  33. 包装类的“==”运算在不遇到算术运算的情况下不会自动拆箱;包装类的equals()方法不处理数据转型。