Java面试题总结

文章目录

一、 java基础

1. String StringBuffer Stringbuilder 异同

  1. 运行速度:StringBuilder>StringBuffer>String
  2. String 是字符串常量,StringBuilder与StringBuffer是字符串变量,所以String对象一旦创建不可修改,后两者是变量,可以修改。
  3. StringBuilder是线程不安全的,StringBuffer线程安全,因为StringBuffer中很多方法可以带有synchronized关键字,所以保证线程安全。
  4. String:适合少量字符串操作
    StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
    StringBuffer:适用于多线程下在字符缓冲区进行大量操作的情况

2.JDBC步骤

(1)装载相应数据库的JDBC驱动

  • 导入专用的jar包
  • 初始化驱动(Class.forName())

(2)建立JDBC与数据库之间的连接

  • Connection c = DriverManager.getConnection(url,username,pwd)

(3)创建statemant或PreparedStatedment接口,执行sql语句

  • Statement与PreparedStatement异同:
    ①都是用来执行sql语句的。
    ②pstmt需要在根据sql语句来创建,可以设置参数,可读性好,不易记错,statement需要字符串拼接,可读性和维护性差
    ③pstmt有预编译机制,性能比statement更快
    ④pstmt能有效防止sql注入

(4)处理和显示结果

  • 执行查询语句,需要把结果集返回给ResultSet,
    ResultSet rs = s.executeQuery(sql);

(5)释放资源

  • 在JDBC编码的过程中我们创建了Connection、ResultSet等资源,这些资源在使用完毕之后是一定要进行关闭的。关闭的过程中遵循从里到外的原则。

3.抽象类与接口的区别?

(1)接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
(2)类不可以多继承,接口可以多实现。
(3)类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
(4)抽象类可以在不提供接口方法实现的情况下实现接口。
(5)Java 接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。
(6)Java 接口中的成员函数默认是 public 的(public static final)。抽象类的成员函数可以是 private,protected 或者是 public 。
(7)接口是绝对抽象的,不可以被实例化(java 8已支持在接口中实现默认的方法)。抽象类也不可以被实例化,但是,如果它包含 main 方法的话是可以被调用的。

扩展:

(1)Java抽象类中不能有静态的抽象方法。

  • 抽象类是不能实例化的,即不能被分配内存;而static修饰的方法在类实例化之前就已经别分配了内存,这样一来矛盾就出现了:抽象类不能被分配内存,而static方法必须被分配内存。所以抽象类中不能有静态的抽象方法

(2)抽象类不一定有抽象方法,可以有静态方法。

  • 静态static是属于字节码的。
    一个抽象类可以没有抽象方法,使用abstract只是为了不被实例化。
    以上两点可以说明,静态方法只要有字节码存在就可以运行,所以抽象类中可以有静态方法。

(3)静态和抽象不能共存在方法上。

  • 因为静态属于字节码,不需要对象就可以运行;而抽象方法没有方法体,运行没有意义,所以不能共存。

(4)java抽象类和普通类的区别

  • 1.抽象类不能被实例化。
    2.抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态。
    3.抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体
    4.含有抽象方法的类必须申明为抽象类
    5.抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类。

4.Lambda表达式

https://blog.csdn.net/zyc88888/article/details/82622137

5.重写和重载的区别?

(1)重载: 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
(2)重写: 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类就不能重写该方法。

6.成员变量与局部变量的区别有那些?

(1)从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所修饰;但是,成员变量和局部变量都能被final所修饰;
(2)从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存
(3)从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
(4)成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被final修饰但没有被static修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。

7.是否可以在static环境中访问非static变量

不可以。
因为静态static是属于字节码的,在类加载之前就已经分配内存了,这时候非静态变量并没有加载,故静态变量不能访问。

8.自动拆箱与自动装箱

装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
Integer i = 10; //装箱
int n = i; //拆箱

9.什么是值传递和引用传递

(1)值传递:传递的是实际参数的一个副本,这个值可能是基本类型,也可能是引用类型的地址.
就是在方法调用的时候,实参是将自己的一份拷贝赋给形参,在方法内,对该参数值的修改不影响原来实参。
(2)引用传递:传递的是实际参数的地址的一个副本.
是在方法调用的时候,实参将自己的地址传递给形参,此时方法内对该参数值的改变,就是对该实参的实际操作。
(3)在java中只有一种传递方式,那就是值传递.可能比较让人迷惑的就是java中的对象传递时,对形参的改变依然会影响到该对象的内容。

10.== 和 equals 的区别是什么?

(1) 如果比较的是基本数据类型,那么比较的是变量的值
   如果比较的是引用数据类型,那么比较的是地址值(两个对象是否指向同一块内存)
(2) equals:如果没有重写equals方法比较的是两个对象的地址值。
   如果重写了equals方法后我们往往比较的是对象中的属性的内容

11.两个对象的 hashCode()相同,则 equals()也一定为 true吗?

按规定重写的情况下:
两个对象equals相等,则它们的hashcode必须相等,反之则不一定。
两个对象双等(==)相等,则它们的hashcode必须相等,反之则不一定。【双等相等,则equals必然相等】
所以总的来说,只要按照规定,则有:
两个对象equals相等,则它们的hashcode必须相等,反之则不一定。

12.java 中的 Math.round(-1.5) 等于多少?

答案:-1
(2)Math.round()方法举例:(Math.round求本身的四舍五入. )

  • Case1:小数点后第一位 = 5
    正数:Math.round(11.5) = 12
    负数:Math.round(-11.5) = -11
    Case2:小数点后第一位 < 5
    正数:Math.round(11.49) = 11
    负数:Math.round(-11.49) = -11
    Case3:小数点后第一位 > 5
    正数:Math.round(11.69) = 12
    负数:Math.round(-11.69) = -12

(2)Math.ceil()求最小的整数,但不小于本身.,ceil的英文意义是天花板,该方法就表示向上取整。
   Math.ceil(11.3) 结果为12。
(3)Math.floor求最大的整数,但不大于本身,floor的英文意义是地板,该方法就表示向下取整。
   Math.floor(11.6)的结果为11
(4)Math.abs求本身的绝对值.

13.如何将字符串反转?

 public static void main(String[] args) {
		String str = "ABCDE";
		System.out.println(reverseStringByStringBuilderApi(str));
		System.out.println(reverseString(str));
	}
	
	public static String reverseStringByStringBuilderApi(String str) {
		if (str != null && str.length() > 0) {
			return new StringBuilder(str).reverse().toString();
		}
		return str;
	}
	
	public static String reverseString(String str) {
		if (str != null && str.length() > 0) {
			int len = str.length();
			char[] chars = new char[len];
			for (int i = len - 1; i >= 0; i--) {
				chars[len - 1 - i] = str.charAt(i);
			}
			return new String(chars);
		}
		return str;
	}

14.String常用方法?

!](https://img-blog.csdnimg.cn/20190723102930165.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzI0MDg4Ng==,size_16,color_FFFFFF,t_70)

15.什么是构造器?与构造方法的区别是什么?

  • 构造器作为一种方法,负责成员变量(域)的初始化。构造器最大的用处就是在创建对象时执行初始化
    (1)构造器不能有以下非访问性质的修饰: abstract, final, native, static, 或者 synchronized。
    (2)构造器没有返回值,也不需要void
    (3)构造器是不能被继承的,所以也不能被重写。
  • 构造方法:构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。

16.获取主机域名的方法

①getHostName 获取此 IP 地址的主机名
②getCanonicalHostName 获取此 IP 地址的完全限定域名

二、JVM相

1.jvm内存分哪几个区?

1.方法区

  • 很少发生GC,用来存储已被虚拟机加载的信息、常量、静态变量和即时编译后的代码数据,该区域线程共享,方法区中有一个运行时常量池。

2.虚拟机栈

  • 内存栈,每个方法执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接和方法出口等信息。
  • 栈线程私有不共享,生命周期与线程相似。
  • 局部变量表用于存放基本数据类型,returnAddress类型(指向一条字节码指令的地址)和对象引用。
  • 操作数栈,存储运算结果及运算操作数,不同于局部变量表通过索引来访问,而是压栈和出栈。
  • 动态链接是将常量池中符号引用在运行期转化为直接引用。

3.本地方法栈

  • 本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。

4. 堆

  • 所有线程中共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都在这里创建,该区域经常发生GC。

5. 程序计数器

  • 内存空间小,字节码解释器在工作时,通过改变这个计数值可以选取下一条需要执行的字节码指令。
    在这里插入图片描述
    在这里插入图片描述

2. 堆和栈的区别

1.存放的内容不同

  • 栈存放基本数据类型和引用数据类型变量,存储的都是局部变量。
  • 堆存放的都是数组和对象,new创建的对象都存放在堆里。

2.内存回收管理不同/空间分配不同

  • 栈,一般由操作系统自动分配释放,栈是私有内存区域,每个方法被执行的时候都会创建一个栈帧,栈帧随着方法的进入和退出,在虚拟机栈中做入栈出栈操作,实现了自动清理内存。
  • 堆,一般由程序员分配释放,线程是共享的,没有确定的销毁时间,因此内存回收主要集中于堆中,在堆中分配的内存由垃圾收集器来管理回收。

3.生命周期不同

  • 栈的生命周期与线程相同,随线程而生,随线程而亡,是线程私有的。
  • 堆的生命周期与JVM相同,JVM启动时创建,JVM停止时销毁,是线程共享的。

4.存取速度、方式不同

  • 栈是有序的,先进后出,存取速度较快,仅次于寄存器,但栈的数据大小与生存周期是必须确定的,缺乏灵活性,栈数据可以共享。
  • 堆是无序的,堆是在运行时动态分配内存,生存期不用提前告诉编译器,所以堆得存取速度慢。

3.垃圾回收机制(GC)

(1)为什么有GC?

  • 安全性考虑
  • 减少内存泄漏
  • 减少程序员工作量

(2)GC原理?

  • 对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小、使用情况。通常,GC采用有向图的方式记录和管理堆中的所有对象。通过这种方式确定哪些对象“可达”,哪些对象是“不可达”的,当GC确定一些对象“不可达”时,GC就有责任回收这些内存空间。

(3)程序员手动通知虚拟机进行垃圾回收?

  • System.gc(),通知GC运行,但是java语言规范不能保证GC一定会执行。

(4)java中哪些内存需要回收?

  • 在java的五个内存区中,本地方法栈,虚拟机栈,程序计数器,是每个线程的私有内存空间,随线程而生,随线程而亡,所以这三个区域得内存分配和回收都是确定的,无需考虑内存回收的问题。
  • 但是方法区和堆,一个接口的多个实现类需要的内存空间可能不一样,我们只有在程序运行期间才知道会创建哪些对象,这部分内存的分配和回收都是动态的,GC关注的是这部分。
  • 所以GC会对方法区和堆进行回收。

(5)既然有GC机制,为什么还会有内存泄漏的情况?

  • 理论上将,java的垃圾回收机制,不会有内存泄漏的情况。然而在实际开发中,可能会存在无用却可达的对象,这些对象不能被GC回收,因此导致了内存泄漏。

(6)GC如何判断对象是否存活?

  • 引用计数法,给每一个对象设置一个计数器,当一个地方引用该对象时计数器加一,引用失效时,计数器减一,当计数器数值为零时,说明此对象没有被引用,也就是“死对象”,将会被垃圾回收。但他无法解决循环问题。
  • 可达性算法(引用链法),从一个被称为GC Roots对象向下开始向下搜索,如果一个对象到GC Roots没有任何引用链相连时,说明此对象不可用。

(7)java中,垃圾收集的方法有哪些?

  • 标记-清除
  • 复制算法
  • 标记-整理
  • 分代收集

4.类加载机制

(1)简述类加载机制

  • 虚拟机把描述类的class文件加载到内存,并对数据进行校验,转换解析和初始化,最终转换成可以被直接调用的java文件,这就是虚拟机的类加载机制。

(2)步骤

  • a.装载:查找和导入文件;
  • b.校验:检查载入class文件数据的正确性;
  • c.准备:给类的静态变量分配存储空间;
  • d.解析:将符号引用转换成直接引用;
  • e.初始化:对类的静态变量,静态代码块执行初始化操作。

(3)什么是类加载器?

  • 实现通过类的权限定名获取类的二进制字节流代码块叫做类加载器。

(4)类加载器有哪些?

  • a.启动类加载器(BootstrapClassLoader),用来加载java核心类库,无法被java程序直接引用。
  • b.扩展类加载器(ExtensionsClassLoader),它用来加载java的扩展库。java虚拟机会提供一个扩展库目录,该类加载器在目录中查找并加载java类。
  • c.系统类加载器(SystemClassLoader),他根据java应用的类路径来加载java类。一般来说,java应用的类都是由它来完成加载的,可以通过ClassLoader.getSystemClassLoader()来获取它。
  • d.用户自定义类加载器,通过继承java.lang.ClassLoader类的方式实现。

(5)双亲委派机制?

  • 类加载器收到加载请求,自己不加载,向上委托给父类加载,父类加载不了,再自己加载。

5.反射

(1)反射机制

  • 反射就是动态加载对象,并对对象进行剖析。在运行状态中,对任意一个类,都能够知道它的所有属性和方法,对于任意一个对象,都能获取它的属性,调用它的信息,对于这种动态获取与动态调用对象的功能称为java的反射机制。

(2)如何使用java反射?

  • a.通过一个全限类名创建一个对象(获取类的对象)
    ①Class.forName()
    ②类名.class
    ③对象.getClass()

  • b.获取构造器对象
    class.getConstrunctor()

  • c.通过class实例构造一个对象
    constructor.newInstance();

  • d.获取属性对象
    class.getFields();

  • e.获取方法对象
    class.getMethod();

  • f.执行调用
    method.invoke();

  • g.示例

 Class clz = Class.forName("com.chenshuyi.reflect.Apple");
 Method method = clz.getMethod("setPrice", int.class);
 Constructor constructor = clz.getConstructor();
 Object object = constructor.newInstance();
 method.invoke(object, 4);

(3)反射作用?

  • 在java中,一个类有两种状态,编译和运行状态,通常我们需要的类是在编译阶段获取的,也就是说直接点出来或new出来,可如果说我想在运行阶段获取这个类的信息的话,就需要反射。
  • 假如有两个类A和B,A需要B类的信息,但是B类还没有创建完成,那么A就不能编译完成,但是我们可以用反射机制,在运行的时候再获取B类的信息。

(4)class.forName()与classLoader的区别?

  • class.forName()除了将类的class文件加载到JVM中,还对类进行解释,执行类的static代码块,还会执行给静态变量赋值的静态代码块。带参的Class.foName()可以控制是否加载static代码块。
  • classLoader只做了一件事,就是将类的class文件加载到JVM中,不会执行static中内容,只有在newInstance才会执行static代码块。

三、java容器(集合)

1.结构图

在这里插入图片描述

2.Collection与Collections的区别?

  • Collection是集合类的上级接口,继承他的接口主要有List和Set。他提供了对集合对象进行基本操作的通用接口方法。
  • Collections是集合类的包装类,他提供了一系列静态方法以实现对各种集合的搜索、排序、线程安全化等操作,其中大多数方法都是进行处理线性表。Collections不能实例化,如同一个工具类,服务于Collection框架。

3.List和Map区别?

  • List是存储单列数据的集合,数据允许重复,有序
  • Map是存储双列数据的集合(键值对),键(key)不可以重复,值(value)允许重复,无序

4.List和Set区别?

  • List:①存储数据有序,可以重复;②检索效率高,插入和删除效率低,会引起元素位置改变。
  • Set:①存储数据无序,不可以重复;②检索效率低下,插入和删除效率高,不会引起元素位置改变。

5.List、Map和Set存取元素是有什么区别?

  • ①Set存元素是不能有重复值,Set集合的add()返回一个boolean,当存入元素已存在时返回fasle(equals判断是否与已存在元素相等),add失败,存入元素不存在时返回true,add成功。
    ②Set是无序的,因此取元素时需要用Iterator遍历。
  • ①List存元素时按先后顺序,也可调用add(int index,Object o)指定位置插入(其实不是把这个对象存入这个集合中,而是在集合中用一个索引指向这个对象,当add多个重复的对象,相当于集合中多个索引指向这个对象)。
    ②List取值是可以调用get(index)根据索引取值。
  • ①Map是双列的集合,存数据时。调用put(key,value),每次存储时要以键值对的形式存储,key不能重复(类似Set元素不能重复);
    ②Map取值时可以调用get(key),获取对应的value,也可以利用Map.Entry对象集合。

6.ArrayList和LinkedList区别?

  • ArrayList底层使用的是数组,具有索引,查询速度比较快,插入和删除速度比较慢。(数组是一块连续的内存,插入和删除都要移动内存)
  • LinkedList底层使用的是链表,不要求内存连续,在当前元素中存放上一个或下一个元素的地址,因此插入和删除效率高,查询时需要从头开始一个一个的找,效率较低。

7.ArrayList、LinkedList与Vector区别?

  • ①同:三者都可动态改变长度的数组。
  • ②不同点:
    a.ArrayList不同步,线程不安全,性能高。
    b.Vector绝大多数方法都是同步的,线程安全,性能低。
    c. LinkedList线程不安全,索引效率低,插入删除效率高。

8.ArrayList、LinkedList与Vector存储性能与特性?

  • ArrayList、Vector使用数组的方式存储数据(索引效率高,插入删除效率低),Vector使用了synchronize方法(线程安全),通常性能上较ArrayList差。LinkedList使用双向链表实现存储,按序号索引需要向前或向后遍历,插入时只需要记录本项的前后项即可,插入速度快。

9.HashMap和HashTable区别?

  • ①HashMap是HashTable的轻量级实现,HashMap允许键值为null(最多只允许一条记录键为null),HashTable不允许。
  • ②HashMap把HashTable中的contains方法去掉了,改成了containsKey和containsValue方法,因为contains方法容易让误解。
  • ③HashTable继承自Dictionary类,而HashMap是java.12引进的Map Interface的一个实现。
  • ④HashMap是非synchronize的。而HashTable是,所以HashTable是线程安全的,多个线程可以共享一个HashTable,而如果没有正确同步的话,多个线城是不能共享HashMap的。所以只有一个线程访问的情况下,HashMap效率较高。
  • ⑤HashTable采用与HashMap采用的hash/rehash算法大概都一样,所以性能不会有很大差异。
  • ⑥HashTable使用Enumeration,HashMap使用Iteration。
  • ⑦HashTabele中,数组默认大小是11,增加的方式是old*2+1;
    HashMapp中,默认数组大小是16,而且一定是2的指数。

10.迭代器 Iterator 是什么?

在Java中,有很多的数据容器,对于这些的操作有很多的共性。Java采用了迭代器来为各种容器提供了公共的操作接口。这样使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。
参考链接:https://blog.csdn.net/meism5/article/details/89917376

11.Iterator和Enumeration异同点

Iterato源码:

package java.util;

public interface Enumeration<E> {

    boolean hasMoreElements();

    E nextElement();
}

Enumeration源码:

package java.util;

public interface Iterator<E> {
    boolean hasNext();

    E next();

    void remove();
}

(1)函数接口不同
Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。
Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。
(2) Iterator支持fail-fast机制,而Enumeration不支持。
Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。
而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
(3)速度不一样
Enumeration 比 Iterator 的遍历速度更快。为什么呢?
这是因为,Hashtable中Iterator是通过Enumeration去实现的,而且Iterator添加了对fail-fast机制的支持;所以,执行的操作自然要多一些。

12.Iterator和ListIterator主要区别在以下方面:

(1). ListIterator有add()方法,可以向List中添加对象,而Iterator不能
(2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
(3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
(4) 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

13.怎么确保一个集合不能被修改?

我们很容易想到用final关键字进行修饰,我们都知道
final关键字可以修饰类,方法,成员变量,final修饰的类不能被继承,final修饰的方法不能被重写,final修饰的成员变量必须初始化值,如果这个成员变量是基本数据类型,表示这个变量的值是不可改变的,如果说这个成员变量是引用类型,则表示这个引用的地址值是不能改变的,但是这个引用所指向的对象里面的内容还是可以改变的

那么,我们怎么确保一个集合不能被修改?首先我们要清楚,集合(map,set,list…)都是引用类型,所以我们如果用final修饰的话,集合里面的内容还是可以修改的。
我们可以做一个实验:
可以看到:我们用final关键字定义了一个map集合,这时候我们往集合里面传值,第一个键值对1,1;我们再修改后,可以把键为1的值改为100,说明我们是可以修改map集合的值的。
那我们应该怎么做才能确保集合不被修改呢?
我们可以采用Collections包下的unmodifiableMap方法,通过这个方法返回的map,是不可以修改的。他会报 java.lang.UnsupportedOperationException错。
同理:Collections包也提供了对list和set集合的方法。
Collections.unmodifiableList(List)
Collections.unmodifiableSet(Set)

四、线程

1.并发与并行?

  • ① 并发,在操作系统中,指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都在同一个处理机上运行。
    ②并行,当系统有一个以上CPU时,一个CPU执行进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行,这种方式成为并行。
  • ③区别:并发,是指多个事情,在同一个时间段内同时发生了;
        并行,是指多个事情,在同一个时间点上同时发生了。
        并发的多个任务之间是互相抢占资源的。
        并行的多个任务之间是不互相抢占资源的。
        只有在多CPU的情况中,才会发生并行,否则,看似同时发生的事情,其实都是并发执行的。

2.什么是线程?

  • 线程是操作系统能够进行运算调度的最小单位,他被包含在进程之中,是进程的实际运作单位。

3.线程与进程的区别?

  • 线程是进程的子集,一个进程可有很多个线程,每条线程并行执行不同的任务。不用的进程使用不同的内存空间,而所有线程共享一片相同的内存空间。

4.java中如何实现线程?

  • 继承java.lang.Thread类
  • 实现java.lang.Runnable接口

5.多线程优缺点?

  • 优点:
    ①使程序响应速度更快
    ②当前没有进行处理的任务可以将处理器时间让给其他任务
    ③可以随时停止任务
    ④可以分别设置各个任务的优先级以及优化性能
  • 缺点:
    ①等候使用共享资源时造成程序的运行速度变慢
    ②对线程进行管理需要额外的cpu
    ③可能出现线程死锁情况。即较长时间的等待或资源竞争会导致死锁情况。

6.start()与run()方法区别?

①start用来启动线程。
②run是thread中的一个普通方法调用,还是在主线程里调用。
③把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用run()方法,是jvm内存机制规定的。
④run()方法必须是public访问权限,返回值为void。

7.Runnable与Callable区别?

  • 相同点:
    ①都是接口  ②都可以应用于Executors中
  • 不同点:
    ①Callable实现call方法,Runnable实现run方法。
    ②Callable可以有返回值,Runnable不能有返回值。
    ③Callable可以抛出checked exception,run()不能
    ④Callable在jdk1.5出现,Runnable在jdk1.1就出现了

8.volatile关键字作用?

  • java代码执行中,为了获取更好的性能,jvm可能会对指令进行重排序,volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存,所以对其他线程是可见的,也在一定程度上降低了代码执行效率。

9.volatile与synchronized关键字对比?

①volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取;synchronized是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
②volatile只能使用在变量级别,synchronized则可以使用在变量,方法。
③volatile仅能实现变量修改的可见性,synchronized可以保证变量修改的可见性和原子性。
④volatile不会造成线程的阻塞,synchronized可能造成线程的阻塞。

10.线程的生命周期?

  • ①新建,当程序使用new关键字创建之后,改线程处于新建状态,此时和其他java对象一样,java虚拟机为其分配了内存,并初始化了成员变量。此时的线程对象没有表现出任何的动态特征,程序也不会执行线程的线程执行体。
  • ②就绪,对象调用了start()方法之后,该线程处于就绪状态,java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态的线程并没有开始运行,他只是表示该线程可以运行了,至于该线程何时运行,取决于jvm里线程调度器的调度。
  • ③运行和阻塞,如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态,当发生如下情况,线程会进入阻塞状态。
      a.线程调用sleep主动放弃所占用的处理器资源;
      b.线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞;
      c.线程在等待某个通知;
      d.线程试图获取一个同步监视器,但该同步监视器正被其他线程锁持有;
      e.程序调用了suspend()方法将该线程挂起,但是这个方法容易导致死锁,所以尽量避免使用该方法。
    当正在执行的线程被阻塞之后,其他线程就获得执行的机会了,被阻塞的线程在合适的时候重新进入就绪状态,而不是运行状态,也就是被阻塞的线程被阻塞之后,必须重新等待线程调度器再次调度他。
    针对上面的几种情况,以下情况会解除上面的阻塞:
      a.调用了sleep方法的线程经过了指定的时间;
      b.线程调用的阻塞式IO方法已返回;
      c.线程在等待某个通知时,另一个线程发起了一个通知;
      d.线程成功获得了试图取得同步监视器;
      e.处于挂起状态的线程被调用了resume恢复方法。
  • ④线程死亡,线程会以以下三种方式结束,结束后处于死亡状态:
      a.run()方法执行完成,线程正常结束;
      b.线程抛出了一个未捕获的Exception或Error;
      c.直接调用该线程的stop()方法,但该方法容易导致死锁,不推荐使用。

11.sleep()与wait()区别?

  • 两者都可以让线程处于冻结状态。
    ①sleep()方法是Thread中定义的,wait()是Object中定义的
    ②sleep()必须人为的为其指定时间,wait()可以指定时间,也可以不指定时间
    ③sleep()方法时间到,线程处于临时阻塞状态或运行状态,wait()如果没有设置时间,必须通过notify()或notifyAll()来唤醒
    ④sleep()不一定非要定义在同步中,wait()必须定义在同步中
    ⑤当二者都定义在同步中,线程执行到sleep(),不会释放锁,线程执行到wait()会释放锁

12.什么是乐观锁与悲观锁?(解决并发问题)

  • 乐观锁,总是假设最好的情况,每次拿数据的时候总是认为别人不会修改,所以不会上锁,但是更新的时候会判断一下在此期间别人有没有更新数据,检查数据是否冲突,如果发现冲突则返回错误信息让用户决定如何去做。(不能解决脏读的情况)
    应用:乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
  • 悲观锁,总是假设最坏的情况,每次拿数据的时候都认为别人会修改,所以每次拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞,直到他拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。
    _ 应用:传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。 _
  • 结论:在实际情况中,如果并发量不大,且不允许脏读的情况下,可以使用悲观锁解决并发问题;如果系统的并发量非常大,这时候悲观锁回带来非常大的性能问题,所以我们就要选择乐观锁的方法。

13.什么是线程池?

  • 创建线程需要花费昂贵的资源与时间,如果任务来了才创建线程,那么响应时间会变长,而且一个进程能创建的线程数有限,为了避免这些问题,在程序启动的时候就会创建若干线程来响应处理,他被称为线程池,里面的线程叫做工作线程。

14.notify 和 notifyAll有什么区别?

  • 多线程可以等待单监控锁,Java API 的设计人员提供了一些方法当等待条件改变的时候通知它们,但是这些方法没有完全实现。notify()方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有用武之地。而notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。

15.Lock和synchronized对比?

  • ①Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
    ②synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
    ③Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
    ④通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
    ⑤Lock可以提高多个线程进行读操作的效率。
    ⑥在JDK1.5中,synchronized是性能低效的。因为这是一个重量级操作,它对性能最大的影响是阻塞式的实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性带来了很大的压力。相比之下使用Java提供的Lock对象,性能更高一些。
    但是,JDK1.6,发生了变化,对synchronize加入了很多优化措施,有自适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在JDK1.6上synchronize的性能并不比Lock差。因此。提倡优先考虑使用synchronized来进行同步。

16.Synchronize关键字?

  • synchronized 可以在任意对象及方法上加锁,而加锁的这段代码称为"互斥区"或"临界区",若一个线程想 要执行synchronized修饰的代码块,首先要
    ①尝试获得锁
    ②如果拿到锁,执行synchronized代码体内容
    ③如果拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,而且是多个线程同时去竞争这把锁。
    注*(线程多了也就是会出现锁竞争的问题,多个线程执行的顺序是按照CPU分配的先后顺序而定的,而并非代码执行的先后顺序)
    ①synchronized 可以修饰方法,修饰代码块,这些都是对象锁。若和static一起使用,则升级为类锁。
    ②synchronized 锁是可以重入的,当一个线程得到了一个对象的锁后,再次请求此对象时是可以再次得到该 对象的锁。锁重入的机制,也支持在父子类继承的场景。
    ③synchronized 同步异步,一个线程得到了一个对象的锁后,其他线程是可以执行非加锁的方法(异步)。但是不能执行其他加锁的方法(同步)。
    ④synchronized 锁异常,当一个线程执行的代码出现异常时,其所持有的锁会自动释放。

五、计算机网络

1. TCP三次握手,四次挥手

(1)三次握手,指建立一次TCP连接时,需要客户端和服务端总共发送三个包以确认连接的建立。

  • ①建立连接时,客户端发送syn包到服务器,并进入到SYN-SEND状态,等待服务器确认
    ②服务器收到SYN包,必须确认客户的SYN包,同时自己也发送一个SYN包,即SYN+ACK包,此时服务器进入SYN-RECV状态。
    ③客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入ESTSABLISHED状态,完成三次握手,客户端与服务器开始传送数据。

(2)四次挥手,指断开一个TCP连接时,需要客户端与服务器总共发送4个包以确认连接的断开。

  • ①Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
    ②Server收到FIN后,发送一个ACK来给Client,确认序号为收到序号+1,Server进入CLOSE_WAIT状态。
    ③Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
    ④Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号收到序号+1,Server进入Closed状态,完成四次挥手。

(3)为什么是三次握手 ,不是两次

  • 一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
    如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

2.TCP/IP协议分层

参考链接:https://www.cnblogs.com/qishui/p/5428938.html
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.输入网址到获得页面的过程

(1)DNS解析
(2)浏览器获得域名对应的IP地址,浏览器向服务器建立连接请求,发起三次握手
(3)TCP/IP连接建立起来后,浏览器向服务器发送HTTP请求。
(4)服务器接收这个请求,并根据路径参数映射到特定的请求处理器进行处理并将处理结果及相应的视图给浏览器
(5)浏览器解析并渲染视图,若遇到对js文件、css文件及图片等静态资源的引用,则重复上述步骤并向服务器请求这些资源
(6)浏览器根据其请求到的资源、数据渲染页面,最终向用户呈现一个完整的页面。

4.forward 和 redirect 的区别?

1.forward(转发)
(1)是服务器内部的重定向,服务器直接访问目标地址的 url网址,把里面的东西读取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的。
(2)关于request: 由于在整个定向的过程中用的是同一个request,因此forward会将request的信息带到被重定向的jsp或者servlet中使用。
2.redirect(重定向)
(1)是客户端的重定向,是完全的跳转。即服务器返回的一个url给客户端浏览器,然后客户端浏览器会重新发送一次请求,到新的url里面,因此浏览器中显示的url网址会发生变化。
(2)因为这种方式比forward多了一次网络请求,因此效率会低于forward。

5.301与302区别

  • 301 redirect: 301 代表永久性转移(Permanently Moved)
    301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
  • 302 redirect: 302 代表暂时性转移(Temporarily Moved )
    302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。

6.Get与Post区别

(1)从功能上讲,GET一般用来从服务器上获取资源,POST一般用来更新服务器上的资源;
(2)从REST服务角度上说,GET是幂等的,即读取同一个资源,总是得到相同的数据,而POST不是幂等的,因为每次请求对资源的改变并不是相同的;进一步地,GET不会改变服务器上的资源,而POST会对服务器资源进行改变;
(3)从请求参数形式上看,GET请求的数据会附在URL之后,即将请求数据放置在HTTP报文的 请求头 中,以?分割URL和传输数据,参数之间以&相连。而POST请求会把提交的数据则放置在是HTTP请求报文的 请求体 中。
(4)就安全性而言,POST的安全性要比GET的安全性高,因为GET请求提交的数据将明文出现在URL上,而且POST请求参数则被包装到请求体中,相对更安全。
(5)从请求的大小看,GET请求的长度受限于浏览器或服务器对URL长度的限制,允许发送的数据量比较小,而POST请求则是没有大小限制的。

7.Http与Https的区别

  • Http协议运行在TCP之上,明文传输,客户端与服务器端都无法验证对方的身份;Https是身披SSL(Secure Socket Layer)外壳的Http,运行于SSL上,SSL运行于TCP之上,是添加了加密和认证机制的HTTP。二者之间存在如下不同:
    (1)端口不同:Http与Https使用不同的连接方式,用的端口也不一样,前者是80,后者是443;
    (2)资源消耗:和HTTP通信相比,Https通信会由于加减密处理消耗更多的CPU和内存资源;
    (3)开销:Https通信需要证书,而证书一般需要向认证机构购买;
  • Https的加密机制是一种共享密钥加密和公开密钥加密并用的混合加密机制。

8.TCP和UDP的区别

  • TCP和UDP是OSI模型中的传输层中的协议。TCP提供可靠的通信传输,而UDP则常被用于广播和细节控制交给应用的通信传输
    TCP/IP协议是一个协议簇。里面包括很多协议的。UDP只是其中的一个
    (1)UDP
    UDP不提供复杂的控制机制,利用IP提供面向无连接的通信服务。并且它是将应用程序发来的数据在收到的那一刻,立刻按照原样发送到网络上的一种机制。 即使是出现网络拥堵的情况下,UDP也无法进行流量控制等避免网络拥塞的行为。此外,传输途中如果出现了丢包,UDO也不负责重发。甚至当出现包的到达顺序乱掉时也没有纠正的功能。如果需要这些细节控制,那么不得不交给由采用UDO的应用程序去处理。换句话说,UDP将部分控制转移到应用程序去处理,自己却只提供作为传输层协议的最基本功能。UDP有点类似于用户说什么听什么的机制,但是需要用户充分考虑好上层协议类型并制作相应的应用程序。
    (2)TCP
    TCP充分实现了数据传输时各种控制功能,可以进行丢包的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在UDP中都没有。此外,TCP作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。TCP通过检验、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。
    (3)区别:
    ①TCP是面向连接的,UDP是无连接的;
    ②TCP是可靠的,UDP是不可靠的;
    ③TCP只支持点对点通信,UDP支持一对一、一对多、多对一、多对多的通信模式;
    ④TCP是面向字节流的,UDP是面向报文的;
    ⑤TCP有拥塞控制机制;UDP没有拥塞控制,适合媒体通信;
    ⑥TCP首部开销(20个字节)比UDP的首部开销(8个字节)要大;

9.JSOP实现原理(跨域)

参考:https://www.cnblogs.com/soyxiaobi/p/9616011.html

(1)跨域:
浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),所以跨域就出现了.
(2)同源
请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.
(3)JSONP
jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议。它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
(4)实现原理
创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。在这里插入图片描述

六、Java Web

1.cookie与session区别

参考:https://www.jianshu.com/p/9a561b36e9f3
链接:https://www.jianshu.com/p/59cb3ecd81a4
这个博主写的非常清晰好理解。

(1)Http协议

  • http协议是无状态的(关闭网页–>断开连接–>打开网页–>重新连接)
    我们浏览网页使用的HTTP协议是无状态的协议,就是说网页一关闭,浏览器和服务端的连接就会断开,下次打开网页又要重新连接,服务器无法从你一打开的连接上恢复上一次的会话,服务器不知道是你又回来了。

(2)cookie

  • 网页浏览器保存用户信息的文件。
    有了cookie情况就不同的了,除非我们之前把你的信息保存在cookie里,在你打开网页和服务器建立连接的时候,把cookie里面的你的信息一起发送给服务器,这样服务器就能从cookie接收到的信息里识别你的身份,让页面提供属于你的内容。
    cookie的存储的数量和字符数量都有限制不超过4kb

  • ①HTTP的Cookie规范
    1个Cookie的大小不超过4KB
    1个服务器最多向1个浏览器保存20个Cookie
    1个浏览器最多可以保存300个Cookie
    ②Cookie的用途
    服务器使用Cookie来跟踪客户端状态
    保存购物车
    显示上次登录名
    ③Cookie与HTTP头
    Cookie是通过HTTP请求和响应头在客户端和服务器端传递的

(3)session
session是指我们访问一个网站的周期。
session在计算机网络应用中被称为“会话控制”。客户端浏览器访问网站的时候,服务器会向客户浏览器发送一个每个用户特有的会话编号sessionID,让他进入到cookie里。服务器同时也把sessionID和对应的用户信息、用户操作记录在服务器上,这些记录就是session。客户端浏览器再次访问时,会发送cookie给服务器,其中就包含sessionID。服务器从cookie里找到sessionID,再根据sessionID找到以前记录的用户信息就可以知道他之前操控些、访问过哪里。
当session超过一定时间(一般为30分钟)没有被访问时,服务器就会认为这个session对应的客户端已经停止活动,然后将这个session删除。用以节省空间。当用户关闭浏览器时,sessionId的信息会丢失,虽然服务器session还在,依然无法访问到session中的数据。
(4)区别
①cookie通常保存在客户端,任何人都可以查看,可以编辑伪造,不安全,
 session是服务端技术,在服务端,安全性较高。
②cookie只能存储String类型的对象,
 session可以存储任意类型。
③cookie存在客户端,对服务器没什么影响,
 session过多时会消耗服务器资源,大型网站会有专门的session服务器
④cookie通过设置指定作用域只能在指定作用域有效,
 Session在整个网页都有效。
⑤cookie可以通过 setMaxAge设置有效时间,即使浏览器关闭了仍然存在,
 关闭网页Session就结束了。

2.cookie禁用了,session还能用吗

  • 上述1-(3)中讲述了session的使用过程,那是不是cookie被禁用了,session就不能用了呢?

(1)①在ASP中,Session必须倚赖Cookie才可用,Session是存储在服务器端的,而Cookie是存储在客户端的,相对而言,Session的安全性和可靠程度都比Cookie高。② 在PHP中,通过相关的配置,可以让Session不依赖Cookie而存在。这是因为:
(2) PHP中的Session在默认情况下是使用客户端的Cookie来保存Session ID的,所以当客户端的cookie出现问题的时候就会影响Session了。必须注意的是:Session不一定必须依赖Cookie,这也是Session相比Cookie的高明之处。当客户端的Cookie被禁用或出现问题时,PHP会自动把Session ID附着在URL中,这样再通过Session ID就能跨页使用Session变量了。但这种附着也是有一定条件的,即“php.ini中的session.use_trans_sid = 1“,或者编译时打开了“–enable-trans-sid”选项。

(3)关闭cookie,使用session的方法
①设置php.ini配置文件中的“session.use_trans_sid = 1”,或者编译时打开打开了“–enable-trans-sid”选项,让PHP自动跨页传递Session ID。
② 手动通过URL传值、隐藏表单传递Session ID。
③用文件、数据库等形式保存Session ID,在跨页过程中手动调用。

详解:https://blog.csdn.net/dccmxj/article/details/79291721

3.JSP和servlet区别?

(1)jsp编译后变成servlet(jvm只能识别java代码)
(2)jsp更擅长表现于页面,servlet更擅长逻辑控制
(3)servlet没有内置对象,jsp中内置对象都是必须通过HttpServletRequest对象,HttpServletResponse和HttpServlet对象得到。

4.JSP内置对象

(1)request对象

  • request 对象是 javax.servlet.httpServletRequest类型的对象。 该对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。(包括头信息、系统信息、请求方式以及请求参数等)。request对象的作用域为一次请求。

(2)response对象

  • response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。response对象也具有作用域,它只在JSP页面内有效。

(3)session对象

  • session 对象是由服务器自动创建的与用户请求相关的对象。服务器为每个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态。session对象内部使用Map类来保存数据,因此保存数据的格式为 “Key/value”。 session对象的value可以使复杂的对象类型,而不仅仅局限于字符串类型。

(4)application对象

  • application 对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。与session对象相比,application对象生命周期更长,类似于系统的“全局变量”。

(5)out对象

  • response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。response对象也具有作用域,它只在JSP页面内有效。

(6)pageContext

  • pageContext 对象的作用是取得任何范围的参数,通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用 pageContext对象。

(7) config对象

  • config 对象的主要作用是取得服务器的配置信息。通过 pageConext对象的 getServletConfig() 方法可以获取一个config对象。当一个Servlet 初始化时,容器把某些信息通过 config对象传递给这个 Servlet。 开发者可以在web.xml 文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。

(8)page对象

  • page 对象代表JSP本身,只有在JSP页面内才是合法的。 page隐含对象本质上包含当前 Servlet接口引用的变量,类似于Java编程中的 this 指针。

(9)exception对象

  • exception 对象的作用是显示异常信息,只有在包含 isErrorPage=“true” 的页面中才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。excepation对象和Java的所有对象一样,都具有系统提供的继承结构。exception 对象几乎定义了所有异常情况。在Java程序中,可以使用try/catch关键字来处理异常情况; 如果在JSP页面中出现没有捕获到的异常,就会生成 exception 对象,并把 exception 对象传送到在page指令中设定的错误页面中,然后在错误页面中处理相应的 exception 对象。

5.JSP四大作用域

(1)page——当前页面有效
(2)request——一次客户端请求
(3)session——当我们向服务端发送一个请求,只要页面不关闭。或者会话未过期(默认30min),或者尾调用HttpServlet的invalidate()方法,接下来的操作都属于同一次会话的范畴:
在JSP中,每当向服务器发送一个请求,服务器响应这个请求的时候,会在客户端的Cookie中写一个session id值。每次发送请求的时候,会将该session id值一起发送到服务器端,服务器端根据该session id值来判断每次请求是否属于同一个session的范畴之内。
(4)application——application的作用域是最广的,它代表着整个Web应用的全局变量,对每一个页面,每一个Servlet都是有效的。当我们在application中设置属性时,这个属性在任意的一个页面都是可以访问的。在application作用域中设置的属性如果不手动调用removeAttribute函数进行删除的话,那么application中的属性将永远不会删除,如果Web容器发生重启,此时application范围内的所有属性都将丢失。

6.什么是CSRF攻击?

CSRF(Cross-site request forgery)跨站请求伪造。一般来说,攻击者通过伪造用户的浏览器的请求,向访问一个用户自己曾经认证访问过的网站发送出去,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等。攻击者利用网站对请求的验证漏洞而实现这样的攻击行为,网站能够确认请求来源于用户的浏览器,却不能验证请求是否源于用户的真实意愿下的操作行为。
解决办法:验证码,请求头中token验证等,参考以下。
作者:饥人谷_Wing
链接:https://www.jianshu.com/p/1573c6ff8635
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

7.什么是XSS攻击?

XSS跨站脚本攻击,实际上是CSS(Cross Site Scripting),但它与CSS同名,所以名字是XSS。实际上,原则是将一段JavaScript代码注入网页。然后当其他用户访问该页面时,他们将运行黑客编写的JS代码来实现一些帐户控制。在了解了原理之后,如何破解黑客的攻击?有很多方法,例如:关键字判断当有一个关键字如脚本、src来代替损坏;返回内容时进行转码,转码尖括号采用Unicode编码格式

8.什么是SQL注入攻击?

SQL注入是一个非常古老的漏洞,现在并不常见。经验不足的人可以避免被SQL注入的风险。让我们首先看一个经典案例:用户经常在登录时写字。例:
$sql = “select * from user where username = '” + userName “’’ and passwd = '” +userPassword + “’”;
在正常情况下会说明:select * from user where username =‘admin’ and passwd =‘mima’,但不幸的是黑客也会编写SQL语句,黑客在输入时输入用户名和密码:user named admin’ or 1 = 1 - ,密码为空,此时拼接出的SQL是:从用户中选择*,其中username =‘admin’ or 1 = 1 - ’ and passwd =’’
你看到了什么? 1 = 1总是成立,后者 - 将注释掉以下SQL,admin用户将成功登录,原理就是这么简单。

七、异常

1.java 异常有哪几种,特点是什么?

Throwable 是所有异常的父类,它有两个直接子类 Error 和 Exception;
其中 Exception 又被继续划分为被检查的异常(checked exception)和运行时的异常(runtime exception,即不受检查的异常);Error 表示系统错误,通常不能预期和恢复(譬如 JVM 崩溃、内存不足等);
被检查的异常(Checked exception)在程序中能预期且要尝试修复(如我们必须捕获 FileNotFoundException 异常并为用户提供有用信息和合适日志来进行调试,Exception 是所有被检查的异常的父类);运行时异常(Runtime Exception)又称为不受检查异常,譬如我们检索数组元素之前必须确认数组的长度,否则就可能会抛出 ArrayIndexOutOfBoundException 运行时异常,RuntimeException 是所有运行时异常的父类。

2.throw 与 throws 的区别是什么?

(1)throw:则是用来抛出一个具体的异常类型。
  用在方法体内,跟的是异常对象名
  只能抛出一个异常对象名
  表示抛出异常,由方法体内的语句处理
  throw则是抛出了异常,执行throw则一定抛出了某种异常
  有两种方式要么是自己捕获异常try…catch代码块,要么是抛出一个异常(throws 异常)
(2)throws:用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用我我就抛给谁。
   用在方法声明后面,跟的是异常类名
   可以跟多个异常类名,用逗号隔开
   表示抛出异常,由该方法的调用者来处理
   throws表示出现异常的一种可能性,并不一定会发生这些异常

3.try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

会!
但返回的还是catch中的值。
如果finally中还有return,那就返回finally中的值。
详解参考:https://blog.csdn.net/qq_31473465/article/details/89857169

4.final、finally、finalize 有什么区别?

(1)final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
(2)finally是异常处理语句结构的一部分,表示总是执行。
(3)finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等。(在垃圾回收的时候会调用被回收对象的此方法。)

八、数据库

一定要看:https://blog.csdn.net/qq_22222499/article/details/79060495#6_43
     https://www.yuque.com/wanglua/wanglu/database-optimization-interview

1.drop、delete、truncate的区别?

  • drop直接删掉表
  • delete删除表中数据,可以加where关键字
  • truncate删除表中数据,再插入时自增长id又从1开始
     
    (1) DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。
    (2) 表和索引所占空间。当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小,而DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉。
    (3) 一般而言,drop > truncate > delete
    (4) 应用范围。TRUNCATE 只能对TABLE;DELETE可以是table和view
    (5) TRUNCATE 和DELETE只删除数据,而DROP则删除整个表(结构和数据)。
    (6) truncate与不带where的delete :只删除数据,而不删除表的结构(定义)drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留,但其状态会变为:invalid。
    (7) delete语句为DML(data maintain Language),这个操作会被放到 rollback segment中,事务提交后才生效。如果有相应的 tigger,执行的时候将被触发。
    (8) truncate、drop是DLL(data define language),操作立即生效,原数据不放到 rollback segment中,不能回滚。
    (9) 在没有备份情况下,谨慎使用 drop 与 truncate。要删除部分数据行采用delete且注意结合where来约束影响范围。回滚段要足够大。要删除表用drop;若想保留表而将表中数据删除,如果于事务无关,用truncate即可实现。如果和事务有关,或老师想触发trigger,还是用delete。
    (10) Truncate table 表名 速度快,而且效率高,因为:?truncate table 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
    (11) TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。
    (12) 对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

九、设计模式

1.单例模式

(1)懒汉式

private static final singleTon;
private SingleTon(){}
public static SingleTon getSingleTon(){
	if(singleTon == null){
		singleTon = new SingleTon();
	}
	renturn singleTon;
}

(2)饿汉式

private static final singleTon = new SingleTon();
private SingleTon(){}
public static SingleTon getSingleTon(){
	return singleTon;
}

(3)区别

https://www.cnblogs.com/crazy-wang-android/p/9054771.html

  • 线程安全:
    ①饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,
    ②懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面的1、2、3,这三种实现在资源加载和性能方面有些区别。
  • 资源加载和性能:
    ①饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,
    ②而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值