一. java基础篇
1.final 关键字的作用?
- 被 final 修饰的类不可以被继承
- 被 final 修饰的方法不可以被重写
- 被 final 修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变.
- 被 final 修饰的方法,JVM 会尝试将其内联,以提高运行效率,被 final 修饰的变量,在编译阶段会存入常量池中.
2.abstract class 和 interface 有什么区别?
- 声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建 abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。
- 接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义 static final 成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换, instanceof 运算符可以用来决定某对象的类是否实现了接口
3. Java 集合类:list、set、queue、map、stack 的特点与用法?
- Map
-
Map 是键值对,键 Key 是唯一不能重复的,一个键对应一个值,值可以重复。
-
TreeMap 可以保证顺序,HashMap 不保证顺序,即为无序的,
-
Map 中可以将 Key 和 Value 单独抽取出来,其中 KeySet()方法可以将所有的 keys 抽取成一个 Set,而 Values()方法可以将 map 中所有的 values 抽取成一个集合。
- Set
- 不包含重复元素的集合,set 中最多包含一个 null 元素,只能用 Iterator 实现单项遍历, Set 中没有同步方法。
- List
- 有序的可重复集合,可以在任意位置增加删除元素,用 Iterator 实现单向遍历,也可用ListIterator 实现双向遍历。
- Queue
- Queue 遵从先进先出原则,使用时尽量避免 add()和 remove()方法,而是使用 offer()来添加元素,使用 poll()来移除元素,它的优点是可以通过返回值来判断是否成功,LinkedList实现了 Queue 接口,Queue 通常不允许插入 null 元素。
- Stack
- Stack 遵从后进先出原则,Stack 继承自 Vector,它通过五个操作对类 Vector 进行扩展允许将向量视为堆栈,它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek()方法、测试堆栈是否为空的 empty 方法等。
- 用法
- 如果涉及堆栈,队列等操作,建议使用 List。
- 对于快速插入和删除元素的,建议使用 LinkedList。如果需要快速随机访问元素的,建议使用ArrayList。
4.说出 ArrayList,Vector, LinkedList 的存储性能和特性?
- ArrayList 和 Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector 由于使用了 synchronized 方法(线程安全),通常性能上较 ArrayList 差,而 LinkedList 使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
5.内存泄漏和内存溢出?
7. int 和 Integer 的区别?
- Integer 是 int 的包装类型,在拆箱和装箱中,二者自动转换.int 是基本类型,直接存数值;而 integer 是对象;用一个引用指向这个对象.由于 Integer 是一个对象,在 JVM 中对象需要一定的数据结构进行描述,相比 int 而言,其占用的内存更大一些.
8. String、StringBuilder、StringBuffer 区别?
String |
字符串常量 |
不可变 |
使用字符串拼接时是不同的 2 个空间 |
|
StringBuffer |
字符串变量 |
可变 |
线程安全 |
字符串拼接直接在字符串后追加 |
StringBuilder 字符串变量 |
可变 |
非线程安全 |
字符串拼接直接在字符串后追加 |
|
- StringBuilder 执行效率高于 StringBuffer 高于 String.
- String 是一个常量,是不可变的,所以对于每一次+=赋值都会创建一个新的对象,StringBuffer 和 StringBuilder 都是可变的,当进行字符串拼接时采用 append 方法,在原来的基础上进行追加,所以性能比 String 要高,又因为 StringBuffer是线程安全的而 StringBuilder 是线程非安全的,所以 StringBuilder 的效率高于 StringBuffer.
- 对于大数据量的字符串的拼接,采用 StringBuffer,StringBuilder.
9. Hashtable 和 Hashmap 的区别?
- HashTable 线程安全,HashMap 非线程安全2、Hashtable 不允许 null 值(key 和 value 都不可以),HashMap 允许 null 值(key 和 value 都可以)。
两者的遍历方式大同小异,Hashtable 仅仅比 HashMap 多一个 elements 方法。
10. 说几个常见的编译时异常?
- SQLException 提供有关数据库访问错误或其他错误的信息的异常。
IOexception 表示发生了某种 I / O 异常的信号。此类是由失败或中断的 I / O 操作产生的
一般异常类 FileNotFoundException 当试图打开指定路径名表示的文件失败时,抛出此异常。
ClassNotFoundException 找不到具有指定名称的类的定义。
EOFException 当输入过程中意外到达文件或流的末尾时,抛出此异常。
11. 方法重载的规则?
- 方法名一致,参数列表中参数的顺序,类型,个数不同。重载与方法的返回值无关,存在于父类和子类,同类中。可以抛出不同的异常,可以有不同修饰符。
12. 方法重写的规则?
- 参数列表、方法名、返回值类型必须完全一致,构造方法不能被重写;
- 声明为 final 的方法不能被重写;
- 声明为 static 的方法不存在重写(重写和多态联合才有意义);
- 访问权限不能比父类更低;
- 重写之后的方法不能抛出更宽泛的异常
- 子类无法重写父类的私有方法
13. throw 和 throws 的区别?
- throw:
throw 语句用在方法体内,表示抛出异常,由方法体内的语句处理。throw 是具体向外抛出异常的动作,所以它抛出的是一个异常实例,执行 throw 一定是抛出了某种异常。
- throws:
throws 语句是用在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理。throws 主要是声明这个方法会抛出某种类型的异常,让它的使用者要知道需要捕获的
- 异常的类型。throws 表示出现异常的一种可能性,并不一定会发生这种异常。
14. 抽象类和接口的区别?
- 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
- 类可以实现很多个接口,但是只能继承一个抽象类
- 类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
- 抽象类可以在不提供接口方法实现的情况下实现接口。
- Java 接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。
- Java 接口中的成员函数默认是 public 的。抽象类的成员函数可以是 private,protecte或者是 public 。
- 接口是绝对抽象的,不可以被实例化(java 8 已支持在接口中实现默认的方法)。抽象类也不可以被实例化,但是,如果它包含 main 方法的话是可以被调用的。
15. Java 的基础类型和字节大小? bit。
byte |
short |
int |
long |
float |
double |
char |
boolean |
8位 |
16 位 |
32位 |
64 位 |
32位 |
64位 |
16位 |
使用八分之一个字节 |
16. 四个访问修饰符合访问级别?
public、protected , 没有访问修饰符、private
17. String 和 StringBuffer 的区别?
- String 和 StringBuffer 主要区别是性能:String 是不可变对象,每次对 String 类型进行操作都等同于产生了一个新的 String 对象,然后指向新的 String 对象.所以尽量不要对 String 进行大量的拼接操作,否则会产生很多临时对象,导致 GC 开始工作,影响系统性能.
StringBuffer 是对象本身操作,而不是产生新的对象,因此在有大量拼接的情况下,我们建议使用 StringBuffer(线程安全).
18. HashSet 的底层实现是什么?
- HashSet 的实现是依赖于 HashMap 的,HashSet 的值都是存储在 HashMap 中的。在 HashSet 的构造法中会初始化一个 HashMap 对象,HashSet 不允许值重复。
因此,HashSet 的值是作为 HashMap 的 key 存储在 HashMap 中的,当存储的值已经存在时返回 false。
19. 抽象类的意义?
- 抽象类的意义可以用三句话来概括: 1、为其他子类提供一个公共的类型2、封装子类中重复定义的内容
- 定义抽象方法,子类虽然有不同的实现,但是定义时一致的
20. 你为什么重写 equals 时必须重写 hashCode 方法?
- hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。如果两个对象相等,则 hashcode 一定也是相同的如果两个对象相等,对两个对象分别调用 equals 方法都返回 true 如果两个对象有相同的 hashcode 值,它们也不一定是相等的因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据).
21. HashSet 和 TreeSet 有什么区别?
- HashSet 是由一个 hash 表来实现的,因此,它的元素是无序的。add(),remove(),contains()
方法的时间复杂度是 O(1)。TreeSet 是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是 O(logn)。
23. 数组在内存中如何分配?
- 当一个对象使用 new 关键字创建的时候,会在堆上分配内存空间,然后才返回到对象的引用。这对数组来说也是一样的,因为数组也是一个对象,简单的值类型的数组,每个数组成员是一个引用(指针)引用到栈上的空间。
24. Java 中怎么创建一个不可变对象?
-
对象的状态在构造函数之后都不能被修改,任何修改应该通过创建一个新对象来实现.
-
所有的对象属性应该都设置为 final
-
对象创建要正确,例如:对象的应用不能在构造函数中被泄露出去
-
对象要设置为 final,确保不要继承的 Class 修改了 immutability 特性
25. Java 中 ++ 操作符是线程安全的吗?
- 不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差。
27. Java 中==和 equals()的区别?
- ==既可以比较基本数据类型,也可以比较引用数据类型
- ==在比较基本数据类型时, 比较的是值, 在比较引用数据类型时, 比较对象的地址
- equals只能比较引用数据类型, 比较对象中的内容是否相同, 在没有重写的情况下也是比较对象的地址
28. final、finalize 和 finally 的不同之处?
- final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 finally 是异常处理语句结构的一部分,表示总是执行。 finalize 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,
可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
29. Java 的多态表现在哪里?
- 多态要有动态绑定,否则就不是多态,方法重载也不是多态(因为方法重载是编译期决定好的,没有后期也就是运行期的动态绑定)
- 当满足这三个条件:1、子父类关系 2、有重写 3、要有父类引用指向子类对象
30. 静态类型有什么特点?
- 静态的属性:随着类的加载而加载,该属性不在属于某个对象,属于整个类
- 静态的方法:直接用类名调用,静态方法里不能访问非静态成员变量
- 静态只能访问静态
31.Java 创建对象的几种方式?
- new 创建新对象
- 通过反射机制
- 采用 clone 机制
- 通过序列化机制 ObjectInputStream
32.Object 中有哪些公共方法?
- Object 是所有类的父类,任何类都默认继承 Object clone 保护方法,实现对象的浅复制,只有实现了 Cloneable 接口才可以调用该方法,否则抛出 CloneNotSupportedException 异常。
- equals 在 Object 中与==是一样的,子类一般需要重写该方法。
- hashCode 该方法用于哈希查找,重写了 equals 方法一般都要重写 hashCode 方法。这个方法在一些具有哈希功能的Collection 中用到。
- getClass 方法,获得运行时类型
- wait 使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。
- wait()方法一直等待,直到获得锁或者被中断。
- wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
33.&和&&的区别?
- &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。
34.在.java 源文件中可以有多个类吗(内部类除外)?
- 一个.java 源文件中可以包括多个类(不是内部类),但是单个文件中只能有一个 public 类,并且该 public 类必须与文件名相同
35.如何正确的退出多层嵌套循环?
36.内部类有什么作用?
38.String 是基本数据类型吗?
- 基本数据类型包括 byte、int、char、long、float、double、boolean 和 short。 java.lang.String 类是 final 类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用 StringBuffer 类
39. static 的用法?
- Static 可以修饰内部类、方法、变量、代码块;Static 修饰的类是静态内部类;Static 修饰的方法是静态方法,表示该方法属于当前类的,而不属于某个对象的,静态方法也不能被重写,可以直接使用类名来调用。在 static 方法中不能使用 this 或者 super 关键字。
- Static 修饰变量是静态变量或者叫类变量,静态变量被所有实例所共享,不会依赖于对象。静态变量在内存中只有一份拷贝,在 JVM 加载类的时候,只为静态分配一次内存。
Static 修饰的代码块叫静态代码块,通常用来做程序优化的。静态代码块中的代码在整个类加载的时候只会执行一次。静态代码块可以有多个,如果有多个,按照先后顺序依次执行。
40. 什么是值传递和引用传递?
- 基本数据类型传递值, 引用数据类型传递地址
- 基本数据类型之间的传递就是值传递,引用数据类型之间的传递就是引用传递
41. 重载和重写的区别?
- 方法的重写 Overriding 和重载 Overloading 是 Java 多态性的不同表现。重写 Overriding
是父类与子类之间多态性的一种表现,重载 Overloading 是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。
42. 成员变量和局部变量的区别有哪些?
- 从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;成员变量和局部变量都能被 final 所修饰;
- 从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存
- 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
- 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被 final 修饰但没有被 static 修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。
43. 静态方法和实例方法有何不同?
- 静态方法和实例方法的区别主要体现在两个方面:
在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
- 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制
44.什么是多态?
- 允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
45.多态的优点?
- 可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆 Circle 类工作,对其他任何圆形几何体,如圆环,也同样工作。
可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。
46. 多态存在的三个必要条件?
- 要有继承。
- 要有方法的重写。
- 父类引用指向子类对象(对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接)
47. TreeMap、HashMap、LindedHashMap 的区别?
- LinkedHashMap 可以保证 HashMap 集合有序。存入的顺序和取出的顺序一致。TreeMap 实现
SortMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。HashMap 不保证顺序,即为无序的,具有很快的访问速度。HashMap 最多只允许一条记录的键为 Null;允许多条记录的值为 Null;HashMap 不支持线程的同步。
48.Java(OOP)面向对象的特征有哪些方面?
-
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
-
继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段
-
封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
-
多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当 A 系统访问 B 系统提供的服务时,B 系统有多种提供服务的方式,但一切对 A 系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)
49.列出一些常见的运行时异常?
- ArithmeticException(算术异常)
- ClassCastException (类转换异常)
- IllegalArgumentException (非法参数异常)
- IndexOutOfBoundsException (下标越界异常)
- NullPointerException (空指针异常)
- SecurityException (安全异常)
50.什么是反射?
- 反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能成为 Java 反射机制。
51.反射的作用?
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
52.获取 class 的三种方式?
- 对象调用 getClass() 方法来获取;类名.class 的方式得到;通过 Class 对象的 forName()
静态方法来获取
53.break 和 continue 的区别?
- break 和 continue 都是用来控制循环的语句。break 用于完全结束一个循环,跳出循环体执行循环后面的语句。continue 用于跳过本次循环,继续下次循环。
54.运行时异常与一般异常有何异同?
- 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java 编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。
55.List、Map、Set 三个接口存取元素时,各有什么特点?
- List 以特定索引来存取元素,可以有重复元素。Set 不能存放重复元素(用对象的 equals() 方法来区分元素是否重复)。Map 保存键值对(key-value pair)映射,映射关系可以是一对一或多对一
56.Collection 和 Collections 的区别?
- Collection 是集合类的上级接口,继承与他的接口主要有 Set 和 List.
Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
57.Error 和 Exception 有什么区别?
- error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。
58.EJB 的生命周期,以及如何管理事务?
- SessionBean:Stateless Session Bean 的生命周期是由容器决定的,当客户机发出请求要建立一个 Bean 的实例时,EJB 容器不一定要创建一个新的 Bean 的实例供客户机调用,而是随便找一个现有的实例提供给客户机。当客户机第一次调用一个 Stateful Session Bean 时,容器必须立即在服务器中创建一个新的 Bean 实例,并关联到客户机上,以后此客户机调用 Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的 Bean 实例。EntityBean:Entity Beans 能存活相对较长的时间,并且状态是持续的。只要数据库中的数据存在,Entity beans 就一直存活。而不是按照应用程序或者服务进程来说的。即使 EJB
容器崩溃了,Entity beans 也是存活的。Entity Beans 生命周期能够被容器或者 Beans 自
己管理。EJB 通过以下技术管理实务:对象管理组织(OMG)的对象实务服务(OTS),Sun Microsystems 的 Transaction Service(JTS)、Java Transaction API(JTA),开发组(X/Open)
的 XA 接口。
59.Comparable 和 Comparator 接口的区别?
- Comparable 接口只包含一个 compareTo()方法。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。Comparator 接口包含 compare()和 equals()两个方法。
60.switch 能否作用在 byte、long、string 上?
- switch 可作用在 char、byte、short、int switch 可作用于 char、byte、short、int 的包装类上
switch 不可作用于 long、double、float、boolean,包括他们的包装类 switch 中可以是字符串类型,String(Java1.7 以后才可以作用在 String 上) switch 可以是枚举类型(JDK1.5 之后)
61.jdk 中哪些类是不能继承的?
- 不能继承的是类是那些用 final 关键字修饰的类。一般比较基本的类型或防止扩展类无意间破坏原来方法的实现的类型都应该是 final 的,在 jdk 中 System,String,StringBuffer 等都是基本类型。
62.Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢?
- Set 里的元素是不能重复的,元素重复与否是使用 equals()方法进行判断的。equals()和==方法决定引用值是否指向同一对象 equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。
63.JDK 和 JRE 的区别是什么?
- Java 运行时环境(JRE)是将要执行 Java 程序的 Java 虚拟机。它同时也包含了执行 applet 需要的浏览器插件。Java 开发工具包(JDK)是完整的 Java 软件开发包,包含了 JRE,编译器和其他的工具(比如:JavaDoc,Java 调试器),可以让开发者开发、编译、执行 Java 应用程序。
64.是否可以在 static 环境中访问非 static 变量?
- static 变量在 Java 中是属于类的,它在所有的实例中的值是一样的。当类被 Java 虚拟机载入的时候,会对 static 变量进行初始化。如果你的代码尝试不用实例来访问非 static 的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
65.Java 支持多继承么?
- 不支持,Java 不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。
66.什么是迭代器(Iterator)?
- Iterator 接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。
克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。
67.Iterator 和 ListIterator 的区别是什么?
- 下面列出了他们的区别:
Iterator 可用来遍历 Set 和 List 集合,但是 ListIterator 只能用来遍历 List。 Iterator 对集合只能是前向遍历,ListIterator 既可以前向也可以后向。
ListIterator 实现了 Iterator 接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
69.List, Set, Map 是否继承自 Collection 接口?
- 只有 List 和 Set 接口继承于 Collection 接口,Map 是与 Collection 并列的接口概念
70.字符串常量池到底存在于内存空间的哪里?
- jdk 6.0 字符串常量池在方法区,方法区的具体体现可以看做是堆中的永久区。 jdk 7.0 java 虚拟机规范中不再声明方法区,字符串常量池存放在堆空间中 jdk 8.0 java 虚拟机规范中又声明了元空间,字符串常量池存放在元空间中
72.用哪两种方式来实现集合的排序?
- 你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有顺序的的集合,如 list,然后通过 Collections.sort() 来排序。
73.说出 JDK 1.7 中的三个新特性?
- 虽然 JDK 1.7 不像 JDK 5 和 8 一样的大版本,但是,还是有很多新的特性,如 try-with-resource 语句,这样你在使用流或者资源的时候,就不需要手动关闭,Java 会自动关闭。Fork-Join 池某种程度上实现 Java 版的 Map-reduce。允许 Switch 中有 String 变量和文本。菱形操作符(<>)用于类型推断,不再需要在变量声明的右边申明泛型,因此可以写出可读写更强、更简洁的代码。另一个值得一提的特性是改善异常处理,如允许在同一个 catch 块中捕获多个异常。
74.说出 5 个 JDK 1.8 引入的新特性?
- Java 8 在 Java 历史上是一个开创新的版本,下面 JDK 8 中 5 个主要的特性: Lambda 表达式,允许像对象一样传递匿名函数 Stream API,充分利用现代多核 CPU,可以写出很简洁的代码 Date 与 Time API,最终,有一个稳定、简单的日期和时间库可供你使用 扩展方法,现在,接口中可以有静态、默认方法。 重复注解,现在你可以将相同的注解在同一类型上使用多次。
75.ArrayList 源码分析?(背诵)
- ArrayList 是一种变长的集合类,基于定长数组实现,使用默认构造方法初始化出来的容量是 10 ( 1.7 之后都是延迟初始化,即第一次调用 add 方法添加元素的时候才将 elementData 容量初始化为 10)。
- ArrayList 允许空值和重复元素,当往 ArrayList 中添加的元素数量大于其底层数组容量时,其会通过扩容机制重新生成一个更大的数组。ArrayList 扩容的长度是原长度的 1.5 倍
- 由于 ArrayList 底层基于数组实现,所以其可以保证在 O(1) 复杂度下完成随机查找操作。
- ArrayList 是非线程安全类,并发环境下,多个线程同时操作 ArrayList,会引发不可预知的异常或错误。
- 顺序添加很方便
- 删除和插入需要复制数组,性能差(可以使用 LinkindList)
- Integer.MAX_VALUE - 8 :主要是考虑到不同的 JVM,有的 JVM 会在加入一些数据头,当扩容后的容量大于 MAX_ARRAY_SIZE,我们会去比较最小需要容量和 MAX_ARRAY_SIZE 做比较,如果比它大, 只能取 Integer.MAX_VALUE,否则是 Integer.MAX_VALUE -8。 这个是从 jdk1.7 开
始才有的 new Object[]
76.HashMap 源码分析?(背诵)
- jdk1.8 之前 list + 链表
- jdk1.8 之后 list + 链表(当链表长度到 8 时,转化为红黑树)
- HashMap 的扩容因子
默认 0.75,也就是会浪费 1/4 的空间,达到扩容因子时,会将 list 扩容一倍,0.75 是时间与空间一个平衡值;
77. ConcurrentHashMap 源码分析?(背诵)
- ConcurrentHashMap 所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。有些方法需要跨段,比如 size()和 containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在 ConcurrentHashMap 内部,段数组是 final 的,并且其成员变量实际上也是 final 的,但是,仅仅是将数组声明为 final 的并不保证数组成员也是 final 的,这需要实现上的保证。这可以确保不会出现死锁,因为获得锁的顺序是固定的。
- ConcurrentHashMap 是由 Segment 数组结构和 HashEntry 数组结构组成。Segment 是一种可重入锁 ReentrantLock,在 ConcurrentHashMap 里扮演锁的角色,HashEntry 则用于存储键值对数据。一个 ConcurrentHashMap 里包含一个 Segment 数组,Segment 的结构和 HashMap
类似,是一种数组和链表结构, 一个 Segment 里包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护者一个 HashEntry 数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得它对应的 Segment 锁。
二、Java Web
1. session 和 cookie 的区别?
- session 是存储在服务器端,cookie 是存储在客户端的,所以安全来讲 session 的安全性要比 cookie 高,然后我们获取 session 里的信息是通过存放在会话 cookie 里的 sessionid 获取的。又由于 session 是存放在服务器的内存中,所以 session 里的东西不断增加会造成服务器的负担,所以会把很重要的信息存储在 session 中,而把一些次要东西存储在客户端的 cookie 里,然后 cookie 确切的说分为两大类分为会话 cookie 和持久化 cookie,会话 cookie 确切的说是,存放在客户端浏览器的内存中,所以说他的生命周期和浏览器是一致的,浏览器关了会话 cookie 也就消失了,然而持久化 cookie 是存放在客户端硬盘中,而持久化 cookie 的生命周期就是我们在设置 cookie 时候设置的那个保存时间,然后我们考虑一问题当浏览器关闭时 session 会不会丢失,从上面叙述分析 session 的信息是通过会话 cookie 的 sessionid 获取的,当浏览器关闭的时候会话 cookie 消失所以我们的 sessionid 也就消失了,但是 session 的信息还存在服务器端,这时我们只是查不到所谓的 session 但它并不是不存在。那么,session 在什么情况下丢失,就是在服务器关闭的时候,或者是 session 过期(默认时间是 30 分钟),再或 者 调 用 了 invalidate() 的 或 者 是 我 们 想 要 session 中 的 某 一 条 数 据 消 失 调 用session.removeAttribute()方法,然后 session 在什么时候被创建呢,确切的说是通过调用getsession()来创建,这就是 session 与 cookie 的区别.
2. session 和 cookie 联系?
- session 是通过 cookie 来工作的 session 和 cookie 之间是通过 C O O K I E [ ′ P H P S E S S I D ′ ] 来联系的,通过 _COOKIE['PHPSESSID']来联系的,通过 COOKIE[′PHPSESSID′]来联系的,通过_COOKIE[‘PHPSESSID’]可以知道 session 的 id,从而获取到其他的信息。
在购物网站中通常将用户加入购物车的商品联通 session_id 记录到数据库中,当用户再次访问是,通过 sessionid 就可以查找到用户上次加入购物车的商品。因为 sessionid 是唯一的,记录到数据库中就可以根据这个查找了。
3. servlet 的生命周期?
-
Servlet 生命周期可以分成四个阶段:加载和实例化、初始化、服务、销毁。
当客户第一次请求时,首先判断是否存在 Servlet 对象,若不存在,则由 Web 容器创建对象,而后调用 init()方法对其初始化,此初始化方法在整个 Servlet 生命周期中只调用一次。
完成 Servlet 对象的创建和实例化之后,Web 容器会调用 Servlet 对象的 service()方法来
处理请求。
-
Web 容器关闭或者 Servlet 对象要从容器中被删除时,会自动调用 destory()方法。
4. 什么是 webservice?
- 从表面上看,WebService 就是一个应用程序向外界暴露出一个能通过 Web 进行调用的 API,也就是说能用编程的方法通过 Web 来调用这个应用程序。我们把调用这个 WebService 的应用程序叫做客户端,而把提供这个 WebService 的应用程序叫做服务端。从深层次看, WebService 是建立可互操作的分布式应用程序的新平台,是一个平台,是一套标准。它定义了应用程序如何在 Web 上实现互操作性,你可以用任何你喜欢的语言,在任何你喜欢的平台上写 Web service ,只要我们可以通过 Web service 标准对这些服务进行查询和访问。
5. jsp 和 servlet 的区别、共同点、各自应用的范围?
- JSP 是 Servlet 技术的扩展,本质上就是 Servlet 的简易方式。JSP 编译后是“类 servlet”。Servlet
和 JSP 最主要的不同点在于,Servlet 的应用逻辑是在 Java 文件中,并且完全从表示层中的 HTML 里分离开来。而 JSP 的情况是 Java 和 HTML 可以组合成一个扩展名为.jsp 的文件。JSP侧重于视图,Servlet 主要用于控制逻辑。在 struts 框架中,JSP 位于 MVC 设计模式的视图层,
而 Servlet 位于控制层.
6.转发(forward)和重定向(redirect)的区别?
- 从地址栏显示来说
forward 是服务器请求资源,服务器直接访问目标地址的 URL,把那个 URL 的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址. redirect 是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的 URL.
- 从数据共享来说
forward:转发页面和转发到的页面可以共享 request 里面的数据.
redirect:不能共享数据. 3. 从运用地方来说
forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等 4. 从效率来说forward:高.
redirect:低.
7. request.getAttribute()和 request.getParameter()有何区别?
- request.getParameter()取得是通过容器的实现来取得通过类似 post,get 等方式传入的数
- request.setAttribute()和 getAttribute()只是在 web 容器内部流转,仅仅是请求处理阶段。
- getAttribute 是返回对象,getParameter 返回字符串
- getAttribute()一向是和 setAttribute()一起使用的,只有先用 setAttribute()设置之后,才能够通过 getAttribute()来获得值,它们传递的是 Object 类型的数据。而且必须在同一个 request 对象中使用才有效。,而 getParameter()是接收表单的 get 或者 post 提交过来的参数
9. MVC 的各个部分都有哪些技术来实现?如何实现?
- MVC 是 Model-View-Controller 的简写。“Model” 代表的是应用的业务逻辑(通过 JavaBean, EJB 组件实现), “View” 是应用的表示面(由 JSP 页面产生),“Controller” 是提供应用的处理过程控制(一般是一个 Servlet),通过这种设计模型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用
11. Http 请求的 get 和 post 方法的区别。
- Get 是向服务器发索取数据的一种请求,而 Post 是向服务器提交数据的一种请求
- Get 是获取信息,而不是修改信息,类似数据库查询功能一样,数据不会被修改
- Get 请求的参数会跟在 url 后进行传递,请求的数据会附在 URL 之后,以?分割 URL 和传输数据,参数之间以&相连,%XX 中的 XX 为该符号以 16 进制表示的 ASCII,如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用
BASE64 加密。
- Get 传输的数据有大小限制,因为 GET 是通过 URL 提交数据,那么 GET 可提交的数据量就跟 URL 的长度有直接关系了,不同的浏览器对 URL 的长度的限制是不同的。
- GET 请求的数据会被浏览器缓存起来,用户名和密码将明文出现在 URL 上,其他人可以查到历史浏览记录,数据不太安全。在服务器端,用 Request.QueryString 来获取 Get 方式提交来的数据
Post 请求则作为 http 消息的实际内容发送给 web 服务器,数据放置在 HTML Header 内提交, Post 没有限制提交的数据。Post 比 Get 安全,当数据是中文或者不敏感的数据,则用 get,因为使用 get,参数会显示在地址,对于敏感数据和不是中文字符的数据,则用 post。
- POST 表示可能修改变服务器上的资源的请求,在服务器端,用 Post 方式提交的数据只能用 Request.Form 来获取。
12. tomcat 容器是如何创建 servlet 类实例?用到了什么原理?
- 当容器启动时,会读取在 webapps 目录下所有的 web 应用中的 web.xml 文件,然后对 xml 文件进行解析,并读取 servlet 注册信息。然后,将每个应用中注册的 servlet 类都进行加载,并通过反射的方式实例化。(有时候也是在第一次请求时实例化)
- 在 servlet 注册时加上1如果为正数,则在一开始就实例化,如果不写或为负数,则第一次请求实例化。
13.JDBC 访问数据库的基本步骤是什么?
第一步:Class.forName()加载数据库连接驱动;
第二步:DriverManager.getConnection()获取数据连接对象;
第三步:根据 SQL 获取 sql 会话对象,有 2 种方式 Statement、PreparedStatement ;
第四步:执行 SQL,执行 SQL 前如果有参数值就设置参数值 setXXX();
第五步:处理结果集;
第六步:关闭结果集、关闭会话、关闭连接。
14.为什么要使用 PreparedStatement?
PreparedStatement 接口继承 Statement,PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象。
作为 Statement 的子类, PreparedStatement 继承了 Statement 的所有功能。三种方法execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要参数。
在 JDBC 应用中,多数情况下使用 PreparedStatement,原因如下:
代码的可读性和可维护性。Statement 需要不断地拼接,而 PreparedStatement 不会。
PreparedStatement 尽最大可能提高性能。DB 有缓存机制,相同的预编译语句再次被调用不会再次需要编译。
最重要的一点是极大地提高了安全性。Statement 容易被 SQL 注入,而 PreparedStatement
传入的内容不会和 sql 语句发生任何匹配关系。
15.数据库连接池的原理。为什么要使用连接池?
1、数据库连接是一件费时的操作,连接池可以使多个操作共享一个连接。
2、数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量、使用情况,为系统开发,测试及性能调整提供依据。
3、使用连接池是为了提高对数据库连接资源的管理
16.execute,executeQuery,executeUpdate 的区别是什么?
1、Statement 的 execute(String query)方法用来执行任意的 SQL 查询,如果查询的结果是一个ResultSet,这个方法就返回 true。如果结果不是 ResultSet,比如 insert 或者 update 查询,它就会返回 false 。我们可以通过它的 getResultSet 方法来获取 ResultSet ,或者通过getUpdateCount()方法来获取更新的记录条数。
2、Statement 的 executeQuery(String query)接口用来执行 select 查询,并且返回 ResultSet。
即使查询不到记录返回的 ResultSet 也不会为 null。我们通常使用 executeQuery 来执行查询语句,这样的话如果传进来的是 insert 或者 update 语句的话,它会抛出错误信息为
“executeQuery method can not be used for update”的 java.util.SQLException。 ,
3、Statement 的 executeUpdate(String query)方法用来执行 insert 或者 update/delete(DML)
语句,或者 什么也不返回,对于 DDL 语句,返回值是 int 类型,如果是 DML 语句的话,它就是更新的条数,如果是 DDL 的话,就返回 0。
只有当你不确定是什么语句的时候才应该使用 execute() 方法,否则应该使用 executeQuery 或者 executeUpdate 方法。
17.JDBC 的 ResultSet 是什么?
在查询数据库后会返回一个 ResultSet,它就像是查询结果集的一张数据表。
ResultSet 对象维护了一个游标,指向当前的数据行。开始的时候这个游标指向的是第一行。如果调用了 ResultSet 的 next()方法游标会下移一行,如果没有更多的数据了,next()方法会返回 false。可以在 for 循环中用它来遍历数据集。
默认的 ResultSet 是不能更新的,游标也只能往下移。也就是说你只能从第一行到最后一行遍历一遍。不过也可以创建可以回滚或者可更新的 ResultSet
当生成 ResultSet 的 Statement 对象要关闭或者重新执行或是获取下一个 ResultSet 的时候,ResultSet 对象也会自动关闭。可以通过 ResultSet 的 getter 方法,传入列名或者从 1 开始的序号来获取列数据。
18.什么是 Servlet?
Servlet 是使用 Java Servlet 应用程序接口(API)及相关类和方法的 Java 程序,所有的 Servlet
都必须要实现的核心接口是 javax.servlet.servlet。每一个 servlet 都必须要直接或者间接实现这个接口,或者继承 javax.servlet.GenericServlet 或 javax.servlet.HTTPServlet。
Servlet 主要用于处理客户端传来的 HTTP 请求,并返回一个响应。
19.doGet 和 doPost 方法有什么区别?
doGet:GET 方法会把名值对追加在请求的 URL 后面。因为 URL 对字符数目有限制,进而限制了用在客户端请求的参数值的数目。并且请求中的参数值是可见的,因此,敏感信息不能用这种方式传递。
doPOST:POST 方法通过把请求参数值放在请求体中来克服 GET 方法的限制,因此,可以发送的参数的数目是没有限制的。最后,通过 POST 请求传递的敏感信息对外部客户端是不可见的。
22.页面间对象传递的方法?
request、session、application、cookie
23.JSP 中动态 INCLUDE 与静态 INCLUDE 的区别?
动态 include 用于 jsp:include 动作实现它总是会检查所含文件的变化,适用于包含动态页面,并且可以带参数。
静态 include 用 include 伪码实现,不会检查所含文件的变化,适用于包含静态页面<%@include file=“include.html”%>.
24.JSP 的四大范围?
JSP 中的四种作用域包括 page、request、session 和 application,具体来说: page 代表与一个页面相关的对象和属性。
request 代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件;需要在页面显示的临时数据可以置于此作用域。 session 代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的 session 中。
application 代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域。
25.BS 与 CS 的联系与区别?
1.硬件环境不同:
C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.
B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网, 租用设备. 信息自己管理. 有比 C/S 更强的适应范围, 一般只要有操作系统和浏览器就行
2.对安全要求不同
C/S 一般面向相对固定的用户群, 对信息安全的控制能力很强. 一般高度机密的信息系统采用 C/S 结构适宜. 可以通过 B/S 发布部分可公开信息.
B/S 建立在广域网之上, 对安全的控制能力相对弱, 可能面向不可知的用户。
3.对程序架构不同
C/S 程序可以更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑. B/S 对安全以及访问速度的多重的考虑, 建立在需要更加优化的基础之上. 比 C/S 有更高的要求 B/S 结构的程序架构是发展的趋势, 从 MS 的.Net 系列的 BizTalk 2000 Exchange 2000 等, 全面支持网络的构件搭建的系统. SUN 和 IBM 推的 JavaBean 构件技术等,使 B/S 更加成熟.
4.软件重用不同C/S 程序可以不可避免的整体性考虑, 构件的重用性不如在 B/S 要求下的构件的重用性
好.B/S 对的多重结构,要求构件相对独立的功能. 能够相对较好的重用.就入买来的餐桌可以再利用,而不是做在墙上的石头桌子
5.系统维护不同
C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级. 升级难. 可能是再做一个全新的系统
B/S 构件组成,方面构件个别的更换,实现系统的无缝升级. 系统维护开销减到最小.用户从网上自己下载安装就可以实现升级.
6.处理问题不同
C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关.应该都是相同的系统
B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是 C/S 无法作到的. 与操作系统平台关系最小.
7.用户接口不同
C/S 多是建立的 Window 平台上,表现方法有限,对程序员普遍要求较高 B/S 建立在浏览器上, 有更加丰富和生动的表现方式与用户交流. 并且大部分难度减低,
减低开发成本.
8.信息流不同
C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低
B/S 信息流向可变化, B-B B-C B-G 等信息、流向的变化, 更像交易中心。
26.说出 Servlet 的生命周期,并说出 Servlet 和 CGI 的区别?
Web 容器加载 Servlet 并将其实例化后,Servlet 生命周期开始,容器运行其 init 方法进行 Servlet 的初始化,请求到达时运行其 service 方法,service 方法自动派遣运行与请求对应的 doXXX 方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其 destroy 方法。与 cgi 的区别在于 servlet 处于服务器进程中,它通过多线程方式运行其 service 方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而 CGI 对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于 servlet。
27.如何防止表单重复提交?
针对于重复提交的整体解决方案:
1.用 redirect(重定向)来解决重复提交的问题
2.点击一次之后,按钮失效
3.通过 loading(Loading 原理是在点击提交时,生成 Loading 样式,在提交完成之后隐藏该样式)
4.自定义重复提交过滤器
28.request 作用?
1、获取请求参数 getParameter()
2、获取当前 Web 应用的虚拟路径 getContextPath
3、转发 getRequestDispatcher(路径).forward(request,response);
4、它还是一个域对象
29.get 请求中文乱码?
1、乱码的根本原因:
浏览器的编码方式 UTF-8 和 服务器的解码方式 ISO-859-1 不一样2、解决方法:
1)第一种方式 使用 URLEncoder 和 URLDecoder 两个类 编解码。先以 iso-8895-1 进行编码,然后再以 utf-8 进行解码
2)第二种方式 使用 String 类的方法进行编解码
3)第三种方式 更改 server.xml 配置文件。
GET 请求是在 URL 地址栏中传递请求参数的,它会被 Tomcat 服务器自动解码,而 Tomcat 服务器默认的字符集也是 ISO-8859-1,所以我们需要修改 Tomcat 服务器的字符集为 UTF-8。
30.post 请求中文乱码问题?
1、post 请求方式乱码的原因是:因为 post 是以二进制流的形式发送到的服务器。服务器收到数据后。默认以 iso-8859-1 进行编码。
2、post 请求乱码解决,只需要在获取请求参数之前调用 request.setCharacterEncoding(“UTF-8”); 方法设置字符集 即可。
31.响应乱码?
1、原因: 由服务器编码,默认使用 ISO-8859-1 进行编码
由浏览器解码,默认使用 GBK 进行解码
2、解决方案方法 1:设置响应头
response.setHeader(“Content-Type”,“text/html;charset=utf-8”);
方法 2:设置响应的内容类型
response.setContentType(“text/html;charset=utf-8”);
通过这种方式可以在响应头中告诉浏览器响应体的编码方式是 UTF-8;同时服务器也会采用该字符集进行编码但需要注意的是,两种方法一定要在 response.getWriter()之前进行。
32.Cookie 对象的缺陷?
1、Cookie 是明文的,不安全
2、不同的浏览器对 Cookie 对象的数量和大小有限制
3、Cookie 对象携带过多费流量
4、Cookie 对象中的 value 值只能是字符串,不能放对象网络中传递数据只能是字符串
33.Session 的运行机制?
1、在服务器端创建 Session 对象,该对象有一个全球唯一的 ID
2、在创建 Session 对象的同时创建一个特殊的 Cookie 对象,该 Cookie 对象的名字是
JSESSIONID,该 Cookie 对象的 value 值是 Session 对象的那个全球唯一的 ID,并且会将这个特殊的 Cookie 对象携带发送给浏览器
3、以后浏览器再发送请求就会携带这个特殊的 Cookie 对象
4、服务器根据这个特殊的 Cookie 对象的 value 值在服务器中寻找对应的 Session 对象,以此来区分不同的用户
34.钝化和活化?
1、Session 与 session 域中的对象一起从内存中被序列化到硬盘上的过程我们称为钝化。服务器关闭时会发生钝化。
2、Session 与 session 域中的对象一起从硬盘上反序列化到内存中的过程我们称为活化。服务器再次开启时会发生活化。
3、要保证 session 域中的对象能和 Session 一起被钝化和活化,必须保证对象对应的类实现
Serializable 接口
35.Filter 的工作原理?
Filter 接口中有一个 doFilter 方法,当我们编写好 Filter,并配置对哪个 web 资源进行拦截后, WEB 服务器每次在调用 web 资源的 service 方法之前,都会先调用一下 filter 的 doFilter 方法,因此,在该方法内编写代码可达到如下目的:
调用目标资源之前,让一段代码执行。
是否调用目标资源(即是否让用户访问 web 资源)。调用目标资源之后,让一段代码执行。
web 服务器在调用 doFilter 方法时,会传递一个 filterChain 对象进来,filterChain 对象是
filter 接口中最重要的一个对象,它也提供了一个 doFilter 方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则 web 服务器就
会调用 web 资源的 service 方法,即 web 资源就会被访问,否则 web 资源不会被访问
36. Filter 链是什么?
在一个 web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链。web服务器根据 Filter 在 web.xml 文件中的注册顺序,决定先调用哪个 Filter,当第一个 Filter 的 doFilter 方法被调用时,web 服务器会创建一个代
表 Filter 链的 FilterChain 对象传递给该方法。在 doFilter 方法中,开发人员如果调用了 FilterChain 对象的 doFilter 方法,则 web 服务器会检查 FilterChain
对象中是否还有 filter,如果有,则调用第 2 个 filter,如果没有,则调用目标资源。
38. Servlet Filter Listener 启动顺序?
启动的顺序为 listener->Filter->servlet.
简单记为:理(Listener)发(Filter)师(servlet).
执行的顺序不会因为三个标签在配置文件中的先后顺序而改变。
三、开源框架
-
MyBatis 的优点?
1、基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响, SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并可重用。
2、与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;3、很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持)。
4、能够与 Spring 很好的集成;
5、提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
3.MyBatis 框架的缺点?
(1)SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写 SQL 语句的功底有一定要求。
(2)SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
-
SpringMVC 工作流程?
1、用户发送请求至前端控制器 DispatcherServlet
2、DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。
3、处理器映射器根据请求 url 找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet。
4、DispatcherServlet 通过 HandlerAdapter 处理器适配器调用处理器
5、执行处理器(Controller,也叫后端控制器)。
6、Controller 执行完成返回 ModelAndView
7、HandlerAdapter 将 controller 执行结果 ModelAndView 返回给 DispatcherServlet
8、DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器
9、ViewReslover 解析后返回具体 View
10、DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet 响应用户
4.什么是SpringMVC?
SpringMVC是spring提供的一个mvc模式的框架
5.MyBatis 框架使用的场合?
(1)MyBatis 专注于 SQL 本身,是一个足够灵活的 DAO 层解决方案。
(2)对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择。
6.Spring 中 beanFactory 和 ApplicationContext 的联系和区别?
BeanFactory 是 spring 中较为原始的 Factory,无法支持 spring 的许多插件,如 AOP 功能、
Web 应用等。
ApplicationContext 接口是通过 BeanFactory 接口派生而来的,除了具备 BeanFactory 接口的
功能外,还具备资源访问、事件传播、国际化消息访问等功能。总体区别如下:
1)使用 ApplicationContext,配置 bean 默认配置是 singleton,无论是否使用,都会被实例化。
优点是预先加载,缺点是浪费内存;2)使用 BeanFactory 实例化对象时,配置的 bean 等到使用的时候才会被实例化。优点是节
约内存,缺点是速度比较慢,多用于移动设备的开发;
3)没有特殊要求的情况下,应该使用 ApplicationContext 完成,ApplicationContext 可以实现
BeanFactory 所有可实现的功能,还具备其他更多的功能。
7.SpringIOC 注入的几种方式?
构造器注入 set 方法注入接口注入
8.拦截器与过滤器的区别?
1、拦截器是基于 java 的反射机制的,而过滤器是基于函数回调
2、拦截器不依赖与 servlet 容器,过滤器依赖与 servlet 容器。
3、拦截器只能对 action 请求起作用,而过滤器则可以对几乎所有的请求起作用。
4、拦截器可以访问 action 上下文、值栈里的对象,而过滤器不能访问。
5、在 action 的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
9.SpringIOC 是什么?
Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
10.AOP 有哪些实现方式?
实现 AOP 的技术,主要分为两大类:
静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;编译时编织(特殊编译器实现)
类加载时编织(特殊的类加载器实现)。
动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
-
解释一下代理模式?
1、代理模式: 代理模式就是本该我做的事,我不做,我交给代理人去完成。就比如,我生产了一些产品,我自己不卖,我委托代理商帮我卖,让代理商和顾客打交道,我自己负责主要产品的生产就可以了。 代理模式的使用,需要有本类,和代理类,本类和代理类共同实现统一的接口。然后在 main 中调用就可以了。本类中的业务逻辑一般是不会变动的,在我们需要的时候可以不断的添加代理对象,或者修改代理类来实现业务的变更。
2、代理模式可以分为: 静态代理 优点:可以做到在不修改目标对象功能的前提下,对目标功能扩展 缺点:因为本来和代理类要实现统一的接口,所以会产生很多的代理类,类太多,一旦接口增加方法,目标对象和代理对象都要维护。 动态代理(JDK 代理/接口代理)代理对象,不需要实现接口,代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象,需要我们指定代理对象/目标对象实现的接口的类型。 Cglib 代理 特点: 在内存中构建一个子类对象,从而实现对目标对象功能的扩展。
3、使用场景: 修改代码的时候。不用随便去修改别人已经写好的代码,如果需要修改的话,可以通过代理的方式来扩展该方法。 隐藏某个类的时候,可以为其提供代理类 当我们要扩展某个类功能的时候,可以使用代理类 当一个类需要对不同的调用者提供不同的调用权限的时候,可以使用代理类来实现。 减少本类代码量的时候。 需要提升处理速度的时候。就比如我们在访问某个大型系统的时候,一次生成实例会耗费大量的时间,我们可以采用代理模式,当用来需要的时候才生成实例,这样就能提高访问的速度。
12.Mybatis 是如何 sql 执行结果封装为目标对象?都有哪些映射形式?
第一种是使用标签,逐一定义数据库列名和对象属性名之间的映射关系。第二种是使用 sql 列的别名功能,将列的别名书写为对象属性名。
有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
13.Spring bean 的生命周期?
1、Spring 容器根据配置中的 bean 定义中实例化 bean。
2、Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。
3 、如果 bean |
实现 BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用 |
setBeanName()。 |
|
4 、如果 bean |
实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 |
setBeanFactory()。 |
|
5、如果存在与 bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization() |
|
方法。 |
|
6、如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。 |
|
7 、 最 后 , 如 果 存 在 与 bean 关 联 的 任 何 BeanPostProcessors , 则 将 调 用 |
|
postProcessAfterInitialization() 方法。 |
|
8、如果 bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。9、如果为 bean 指定了 destroy 方法( 的 destroy-method 属性),那么将调用它。 |
|
51 |
|
14.Spring 框架中都用到了哪些设计模式?
代理模式,在 AOP 中被使用最多。
单例模式,在 Spring 配置文件中定义 bean 的时候默认的是单例模式。工厂模式, BeanFactory 用来创建对象的实例。
模板方法, 用来解决重复性代码。
前端控制器,Spring 提供了 DispatcherSerclet 来对请求进行分发。视图帮助,Spring 提供了一系列的 JSP 标签。
依赖注入,它是惯穿于 BeanFactory/ApplicationContext 接口的核心理念。
16.使用 Sping 框架的好处是什么?
1、简化开发,解耦,集成其它框架。
2、低侵入式设计,代码污染级别级别。
3、Spring 的 DI 机制降低了业务对象替换的复杂性,提高了软件之间的解耦。
4、Spring AOP 支持将一些通用的任务进行集中式的管理,例如:安全,事务,日志等,从而使代码能更好的复用。
17.解释 Spring 支持的几种 bean 的作用域?(前面两个记住,后面背诵)
当通过 Spring 容器创建一个 Bean 实例的时候,不仅可以完成 bean 实例的实力化,还可以为 bean 指定作用域。Spring bean 元素的支持以下 5 种作用域:
Singleton:单例模式,在整个 spring IOC 容器中,使用 singleton 定义的 bean 将只有一个实
例。
Prototype:多例模式,每次通过容器中的 getBean 方法获取 prototype 定义的 beans 时,都会产生一个新的 bean 的实例。
Request:对于每次 Http 请求,使用 request 定义的 bean 都会产生一个新的实例,只有在 web 应用时候,该作用域才会有效。
Session:对于每次 Http Session,使用 session 定义的 Bean 都将产生一个新的实例。Globalsession:每个全局的 Http Sesisonn,使用 session 定义的本都将产生一个新的实例
18.在 Spring 中如何注入一个 java 集合?
Spring 提供理论四种集合类的配置元素:
lt;List&: 该标签用来装配 有重复值的 list 值
lt;set&: 该标签用来装配没有重复值的 set 值lt;map&:该标签科以用来注入键值对 lt;props&: 该标签用来支持注入键值对和字符串类型键值对。
19.什么是 Spring bean?
它们是构成用户应用程序主干的对象。
Bean 由 Spring IoC 容器管理。
它们由 Spring IoC 容器实例化,配置,装配和管理。 Bean 是基于用户提供给容器的配置元数据创建。
23.Spring 的重要注解?
@Controller - 用于 Spring MVC 项目中的控制器类。 @Service - 用于服务类。
@RequestMapping - 用于在控制器处理程序方法中配置 URI 映射。
@ResponseBody - 用于发送 Object 作为响应,通常用于发送 XML 或 JSON 数据作为响应。
@PathVariable - 用于将动态值从 URI 映射到处理程序方法参数。
@Autowired - 用于在 spring bean 中自动装配依赖项。
@Qualifier - 使用 @Autowired 注解,以避免在存在多个 bean 类型实例时出现混淆。 @Scope - 用于配置 spring bean 的范围。
@Configuration,@ComponentScan 和 @Bean - 用于基于 java 的配置。@Aspect,@Before,@After,@Around,@Pointcut - 用于切面编程(AOP)。
24.@Component, @Controller, @Repository, @Service 有何区别?
1、 @Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。 spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。
2、@Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。
3、@Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。
4、@Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO
提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。
27.Spring AOP(面向切面)编程的原理?
1、AOP 面向切面编程,它是一种思想。它就是针对业务处理过程中的切面进行提取,以达到优化代码的目的,减少重复代码的目的。 就比如,在编写业务逻辑代码的时候,我们习惯性的都要写:日志记录,事物控制,以及权限控制等,每一个子模块都要写这些代码,代码明显存在重复。这时候,我们运用面向切面的编程思想,采用横切技术,将代码中重复的部分,不影响主业务逻辑的部分抽取出来,放在某个地方进行集中式的管理,调用。 形成日志切面,事物控制切面,权限控制切面。 这样,我们就只需要关系业务的逻辑处理,即提高了工作的效率,又使得代码变的简洁优雅。这就是面向切面的编程思想,它是面向对象编程思想的一种扩展。
2、AOP 的使用场景: 缓存、权限管理、内容传递、错误处理、懒加载、记录跟踪、优化、
校准、调试、持久化、资源池、同步管理、事物控制等。 AOP 的相关概念: 切面(Aspect)
连接点(JoinPoint) 通知(Advice) 切入点(Pointcut) 代理(Proxy): 织入(WeaVing)3、Spring AOP 的编程原理? 代理机制 JDK 的动态代理:只能用于实现了接口的类产生代理。 Cglib 代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强技术,生成当前类的子类对象。
28.Spring MVC 框架有什么用?
Spring Web MVC 框架提供 模型-视图-控制器 架构和随时可用的组件,用于开发灵活且松散耦合的 Web 应用程序。 MVC 模式有助于分离应用程序的不同方面,如输入逻辑,业务逻辑和 UI 逻辑,同时在所有这些元素之间提供松散耦合。
31.Mybatis 中#{}和${}的区别是什么?
#{}是预编译处理,KaTeX parse error: Expected 'EOF', got '#' at position 22: …替换。 Mybatis 在处理#̲{}时,会将 sql 中的#{…{}时,就是把${}替换成变量的值。使用#{}可以有效的防止 SQL 注入,提高系统安全性。
32.Spring 中@Autowire 与@Resource 的区别?
@Autowire 默认按照类型装配,默认情况下它要求依赖对象必须存在如果允许为 null,可以设置它 required 属性为 false,如果我们想使用按照名称装配,可以结合@Qualifier 注解一起使用; @Resource 默认按照名称装配,当找不到与名称匹配的 bean 才会按照类型装配,可以通过
name 属性指定,如果没有指定 name 属性,当注解标注在字段上,即默认取字段的名称作为 bean 名称寻找依赖对象,当注解标注在属性的 setter 方法上,即默认取属性名作为 bean 名称寻找依赖对象
33.什么是控制反转(IOC),什么是依赖注入(DI)?
IOC:就是对象之间的依赖关系由容器来创建,对象之间的关系本来是由我们开发者自己创建和维护的,在我们使用 Spring 框架后,对象之间的关系由容器来创建和维护,将开发者做的事让容器做,这就是控制反转。BeanFactory 接口是 Spring Ioc 容器的核心接口。
DI:我们在使用 Spring 容器的时候,容器通过调用 set 方法或者是构造器来建立对象之间的依赖关系。
控制反转是目标,依赖注入是我们实现控制反转的一种手段。
34.Spring 运行原理?
1、内部最核心的就是 IOC 了,之前是 new 对象,现在可以直接从容器中获取,动态注入,这其实就是利用 java 里的反射。反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,根据 xml Spring 的配置文件来动态的创建对象,和调用对象里的方法的。
2、Spring 另一个核心就是 AOP 面向切面编程,可以为某一类对象 进行监督和控制(也就是在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过配置类达到的。(日志、事务等)
3、Spring 目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring 根据这些配置 内部通过反射去动态的组装对象)要记住: Spring 是一个容器,凡是在容器里的对象才会有 Spring 所提供的这些服务和功能。
4、Spring 里用的最经典设计模式:模板方法模式。(有兴趣同学可以了解一下)、核心容器组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
36. SpringMVC 的运行流程?
DispatcherServlet 前置控制器 |HandlerMapping 请求映射(到 Controller)
|HandlerAdapter 请求映射(到 Controller 类的方法上)|Controller 控制器| HandlerIntercepter 拦截器|ViewResolver 视图映射|View 视图处理