牛客-刷题

本文最后更新于:9 个月前

人生如戏,我们都是自己故事的主角,用心演绎,精彩纷呈。

  • 都是刷题时看到的一些精彩的题解和 Java 基础知识,随手复制粘贴就扔这儿了
  • 就这部分内容,九月底考 Java 二级的时候过了一遍的,还是相当有用的(2023/12/22 早)

1
2
3
4
5
final修饰的方法,不允许被子类覆盖。
final修饰的类,不能被继承。
final修饰的变量,不能改变值。
final修饰的引用类型,不能再指向别的东西,但是可以改变其中的内容。
final修饰的成员变量在赋值时可以有三种方式。1、在声明时直接赋值。2、在构造器中赋值。3、在初始代码块中进行赋值。
1
2
3
4
5
6
7
8
关于抽象类
JDK 1.8以前,抽象类的方法默认访问权限为protected
JDK 1.8时,抽象类的方法默认访问权限变为default

关于接口
JDK 1.8以前,接口中的方法必须是public
JDK 1.8时,接口中的方法可以是public的,也可以是default
JDK 1.9时,接口中的方法可以是private
1
2
3
4
写法顺序:select--from--where--group by--having--order by 

执行顺序:from--where--group by--having--select--order by
就是select要放后面,如果有order by,则order by放最后,因为order by 是对结果进行排序
1
可串行化调度:所有的事物依次逐个执行,这样事物之间就完全不可能有干扰,防止脏读、不可重复读、幻读。
1
2
3
4
客户端对象:Socket s = new Socket("127.0.0.1",6666);
服务端对象:ServerSocket ss = new ServerSocket(6666);
监听服务器的连接:
    s=ss.accept()
1
s.getBytes("GBK").length就是求的字节数。如果是GBK,一个中文字符占2字节,如果是UTF-8则是3个字节,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Java一维数组有两种初始化方法
1、静态初始化
int array[] = new int[]{1,2,3,4,5}
或者
int array[] = {1,2,3,4,5}
需要注意的是,写成如下形式也是错误的
int array[] = new int[5]{1,2,3,4,5}
2、动态初始化
int array[] = new int[5];
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
array[4] = 5;
静态与动态初始化的区别就在于,前者是声明的时候就初始化,后者是先声明,再动态初始化
1
2
3
4
小到大算自动类型转换
就是隐式转换(自动类型转换):
数值型数据的转换:byteshortintlongfloatdouble
字符型转换为整型:charint
1
Java一个源程序只能有一个public类存在,且类名与文件名相同。Java程序是从main方法开始执行的,public为类加载器提供入口,然后找到public类中的main方法开始执行。如果存在多个public类,程序将不知道该从哪里执行。
1
ava分为基本数据据类型和引用数据类型,基本数据类型又分为数值型(整数类型(byteshortintlong)和浮点型(floatdouble))、字符型(char)和布尔型(boolean),引用数据类型包括类(class)、接口(interface)、数组和一些特殊的null类型。
1
2
JDK=JRE+编译、运行等命令工具
      JRE=JVM+Java系统类库
1
Servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载。 (1)加载:容器通过类加载器使用servlet类对应的文件加载servlet (2)创建:通过调用servlet构造函数创建一个servlet对象 (3)初始化:调用init方法初始化 (4)处理客户请求:每当有一个客户请求,容器会创建一个线程来处理客户请求 (5)卸载:调用destroy方法让servlet自己释放其占用的资源
1
2
3
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。

核心容器,Spring上下文,Spring AOP, Spring DAO, Spring ORM, Spring Web, Spring MVC
1
2
3
4
5
6
7
8
9
10
方法重载(overload):
1.必须是同一个类
2方法名(也可以叫函数)一样
3参数类型不一样或参数数量不一样

方法的重写(override)两同两小一大原则:
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限
1
Jdbc六大步骤: 1.注册驱动 2.获取连接 3.创建语句对象 4.执行sql 5.处理语句集 6关闭连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。
节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
JAVA常用的节点流:
文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流。
字符串 StringReader StringWriter 对字符串进行处理的节点流。
数 组 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)。
管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter对管道进行处理的节点流。
常用处理流(关闭处理流使用关闭里面的节点流)
缓冲流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter  增加缓冲功能,避免频繁读写硬盘。
转换流:InputStreamReader OutputStreamReader 实现字节流和字符流之间的转换。
数据流 DataInputStream DataOutputStream  等-提供将基础数据类型写入到文件中,或者读取出来.
流的关闭顺序
一般情况下是:先打开的后关闭,后打开的先关闭
另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b。例如,处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b
可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。
1
2
3
4
Integer对象的方法
Integer.parseInt("");是将字符串类型转换为int的基础数据类型
Integer.valueOf("")是将字符串类型数据转换为Integer对象
Integer.intValue();是将Integer对象中的数据取出,返回一个基础数据类型int
1
在这里帮大家总结一下hashMap和hashtable方面的知识点吧: 1.  关于HashMap的一些说法: a)  HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。HashMap的底层结构是一个数组,数组中的每一项是一条链表。 b)  HashMap的实例有俩个参数影响其性能: “初始容量” 和 装填因子。 c)  HashMap实现不同步,线程不安全。  HashTable线程安全 d)  HashMap中的key-value都是存储在Entry中的。 e)  HashMap可以存null键和null值,不保证元素的顺序恒久不变,它的底层使用的是数组和链表,通过hashCode()方法和equals方法保证键的唯一性 f)  解决冲突主要有三种方法:定址法,拉链法,再散列法。HashMap是采用拉链法解决哈希冲突的。 注:链表法是将相同hash值的对象组成一个链表放在hash值对应的槽位;    用开放定址法解决冲突的做法是:当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。   拉链法解决冲突的做法是: 将所有关键字为同义词的结点链接在同一个单链表中。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。在拉链法中,装填因子α可以大于1,但一般均取α≤1。拉链法适合未规定元素的大小。     2.  Hashtable和HashMap的区别: a)   继承不同。  public class Hashtable extends Dictionary implements Map public class HashMap extends  AbstractMap implements Map bHashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。 cHashtable 中, keyvalue 都不允许出现 null 值。 在 HashMap 中, null 可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为 null 。当 get() 方法返回 null 值时,即可以表示 HashMap 中没有该键,也可以表示该键所对应的值为 null 。因此,在 HashMap 中不能由 get() 方法来判断 HashMap 中是否存在某个键, 而应该用 containsKey() 方法来判断。 d)  两个遍历方式的内部实现上不同。HashtableHashMap都使用了Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式。 e)  哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。 fHashtableHashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTablehash数组默认大小是11,增加的方式是old*2+1HashMaphash数组的默认大小是16,而且一定是2的指数。   注:  HashSet子类依靠hashCode()和equal()方法来区分重复元素。      HashSet内部使用Map保存数据,即将HashSet的数据作为Mapkey值保存,这也是HashSet中元素不能重复的原因。而Map中保存key值的,会去判断当前Map中是否含有该Key对象,内部是先通过keyhashCode,确定有相同的hashCode之后,再通过equals方法判断是否相同。
1
2
3
4
重写 要求两同两小一大原则, 方法名相同,参数类型相同,子类返回类型小于等于父类方法返回类型, 子类抛出异常小于等于父类方法抛出异常, 子类访问权限大于等于父类方法访问权限。[注意:这里的返回类型必须要在有继承关系的前提下比较]
重载 方法名必须相同,参数类型必须不同,包括但不限于一项,参数数目,参数类型,参数顺序
再来说说这道题 A B 都是方法名和参数相同,是重写,但是返回类型没与父类返回类型有继承关系,错误 D 返回一个类错误 c的参数类型与父类不同,所以不是重写,可以理解为广义上的重载访问权限小于父类,都会显示错误
虽然题目没点明一定要重载或者重写,但是当你的方法名与参数类型与父类相同时,已经是重写了,这时候如果返回类型或者异常类型比父类大,或者访问权限比父类小都会编译错误
1
2
3
4
5
6
7
8
9
10
难道我们只能单纯的背java的那个类是线程安全的,那个类不是线程安全的么?
这和授人以鱼有何区别呢?难道就没有一种方法授人以渔?直接教我们如何去判断一个类是否是线程安全的?
java中的线程安全是什么:
就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问
什么叫线程安全:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
看过vector源码的同学就会知道他的许多操作都是加了synchronized修饰的比如他的添加元素。(不知道synchronized是什么意思的自行百度!)
1
只要是被子类重写的方法,不被super调用都是调用子类方法
1
一旦在finally块中使用了returnthrow语句,将会导致try块,catch块中的returnthrow语句失效
1
2
3
4
5
6
7
8
9
链接:https://www.nowcoder.com/questionTerminal/073fe9f1e5c84a689bcdb9ea899d295e?
来源:牛客网

对于管道,有下面这几种类型:
①普通管道(PIPE):通常有两种限制,一是单工,即只能单向传输;二是血缘,即常用于父子进程间(或有血缘关系的进程间)。
②流管道(s_pipe):去除了上述的第一种限制,实现了双向传输。

③命名管道(name_pipe):去除了上述的第二种限制,实现了无血缘关系的不同进程间通信。
显然,要求是对于不同的服务器之间的通信,是要要求全双工形式的,而管道只能是半双工,虽然可以双向,但是同一时间只能有一个方向传输,全双工和半双工的区别可以如下图示理解:

链接:https://www.nowcoder.com/questionTerminal/073fe9f1e5c84a689bcdb9ea899d295e?
来源:牛客网img**

1
is-a:继承关系 has-a:从属关系 like-a:组合关系
1
2
3
4
5
6
7
链接:https://www.nowcoder.com/questionTerminal/049085c1e4204b20b6171a0c13dfbfe7?
来源:牛客网

java.lang.NullPoninterException:变量未被初始化、对象未赋值、对象为空(俗称的空指针异常)
java.lang.NumberFormatException:数据格式转换失败(integer的取值范围为:-128~127,超过范围都会访问false)
java.lang.RuntimeException:运行时异常
java.lang.ArrayindexOutOfBoundsException:数组下标越界
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
链接:https://www.nowcoder.com/questionTerminal/22a7fd3328124530be8ced520a9eaceb?
来源:牛客网

接口是一种特殊的抽象类,先说明抽象类中的抽象方法,再说明接口

抽象类中的抽象方法(其前有 abstract1修饰)不能用 privatestaticsynchronized、na
tive访回修饰符修饰。原因如下:
1. private
抽象方法没有方法体,是用来被继承的,所以不能用 private修饰;
2.static
static修饰的方法可以通过类名来访间该方法(即该方法的方法体),抽象方法用sttic修饰没有意义;
1. synchronized
该关键字是为该方法加一个锁。而如果该关键字修饰的方法是 static方法。则使用的锁就是class变量的锁。如果是修饰类方法。则用this变量锁。
但是抽象类不能实例化对象,因为该方法不是在该抽象类中实现的。是在其子类实现的。所以,锁应该归其子类所有。所以,抽象方法也就不能用 synchronized关键字修饰了;
1. native
native这个东西本身就和 abstract冲突,他们都是方法的声明,只是一个把方法实现移交给子类,另一个是移交给本地操作系统。如果同时出现,就相当于即把实现移交给子类,又把实现移交给本地操作系统,那到底谁来实现具体方法呢

终于说到了接口!
接口是一种特殊的抽象类,接口中的方法全部是抽象方法(但其前的 abstract可以省略),所以抽象类中的抽象方法不能用的访间修饰符这里也不能用。同时额外说明一下protect关键词
4. protect
protected访同修饰符也不能使用,因为接口可以让所有的类去实现(非继承),不只是其子类,但是要用public去修饰。接口可以去继承一个已有的接口。
1
2
3
我们一般使用thread都是new一个线程,然后调用start方法启动,使用start方法才真正实现了多线程运行,thread线程有5种状态,创建-就绪-运行-阻塞-死亡,我们的start方法呢就是就绪这一步,因为这个时候我们的线程并没有立即的执行,而是得等待,等到我们的cpu有空闲的时候,才会执行线程里面的run方法,等run方法执行完了,线程就结束了。

直接使用thread执行run方***咋样呢?因为run方法是thread里面的一个普通的方法,所以我们直接调用run方法,这个时候它是会运行在我们的主线程中的,因为这个时候我们的程序中只有主线程一个线程,所以这样并没有做到多线程的这种目的。
1
2
3
volatile关键字有两个作用:
1.并发环境可见性:volatile修饰后的变量能够保证该变量在线程间的可见性,线程进行数据的读写操作时将绕开工作内存(CPU缓存)而直接跟主内存进行数据交互,即线程进行读操作时直接从主内存中读取,写操作时直接将修改后端变量刷新到主内存中,这样就能保证其他线程访问到的数据是最新数据
2.并发环境有序性:通过对volatile变量采取内存屏障(Memory barrier)的方式来防止编译重排序和CPU指令重排序,具体方式是通过在操作volatile变量的指令前后加入内存屏障,来实现happens-before关系,保证在多线程环境下的数据交互不会出现紊乱。
1
中间件位于操作系统之上,应用软件之下,而不是操作系统内核中
1
2
3
4
5
>>为带符号右移,右移后左边的空位被填充为符号位

>>>为不带符号右移,右移后左边的空位被填充为0

没有<<< 因为<<后右边总是补0
1
2
3
4
5
6
7
java.exe是java虚拟机

javadoc.exe用来制作java文档

jdb.exe是java的调试器

javaprof,exe是剖析工具
1
2
3
4
5
6
7
8
@Autowired
注入声明的SpringBean对象,根据一定的规则首先按照注入的类型去查找,如果没有找到安装注入的名称去匹配你要注入的属性名称,如果都没有找到启动项目时抛出异常,@Autowired(required = false) 表示没有找到注入对象时,不抛异常,注入null。


@Primary
如果有多个相同类型的SpringBean,我们可以使用@Primary注解,优先注入带该注解标识的类,@Primary可以在多个类上标注,那就会抛异常。
@Quelifier
使用SpringBean的名称(SpringBean的名称都是唯一的)进行注入
1
2
3
4
序列化:将数据结构转换称为二进制数据流或者文本流的过程。序列化后的数据方便在网络上传输和在硬盘上存储。
反序列化:与序列化相反,是将二进制数据流或者文本流转换称为易于处理和阅读的数据结构的过程。

本质其实还是一种协议,一种数据格式,方便数据的存储和传输。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
intint之间,用==比较,肯定为true。基本数据类型没有equals方法
intInteger比较,Integer会自动拆箱,== 和 equals都肯定为true
intnew Integer比较,Integer会自动拆箱,调用intValue方法, 所以 == 和 equals都肯定为true
IntegerInteger比较的时候,由于直接赋值的话会进行自动的装箱。所以当值在[-128,127]中的时候,由于值缓存在IntegerCache中,那么当赋值在这个区间的时候,不会创建新的Integer对象,而是直接从缓存中获取已经创建好的Integer对象。而当大于这个区间的时候,会直接new Integer
IntegerInteger进行==比较的时候,在[-128,127]区间的时候,为true。不在这个区间,则为false
IntegerInteger进行equals比较的时候,由于Integer的equals方法进行了重写,比较的是内容,所以为true

Integernew Integernew Integer会创建对象,存储在堆中。而Integer在[-128,127]中,从缓存中取,否则会new Integer.
所以 Integernew Integer 进行==比较的话,肯定为false ; Integernew Integer 进行equals比较的话,肯定为true

new Integernew Integer进行==比较的时候,肯定为false ; 进行equals比较的时候,肯定为true
原因是new的时候,会在堆中创建对象,分配的地址不同,==比较的是内存地址,所以肯定不同

装箱过程是通过调用包装器的valueOf方法实现的
拆箱过程是通过调用包装器的xxxValue方法实现的(xxx表示对应的基本数据类型)

总结:Byte、Short、Integer、Long这几个类的valueOf方法实现类似的。所以在[-128,127]区间内,==比较的时候,值总是相等的(指向的是同一对象),在这个区间外是不等的。
FloatDouble则不相等, Boolean的值总是相等的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
File类的一下常用方法和说明

1.访问文件名相关方法:

String getName(); 返回此File对象所表示的文件名和路径名(如果是路径,则返回最后一级子路径名)。

String getPath(); 返回此File对象所对应的路径名。

File getAbsolutePath(); 返回此File对象所对应的绝对路径名。

String getParent(); 返回此File对象所对应目录(最后一级子目录)的父路径名。

boolean renameTo(File newName); 重命名此File对象所对应的文件或目录,如果重命名成功,则返回true:否则返回false.(A)

2.文件检测相关方法

boolean exists(); 判断File对象所对应的文件或目录是否存在。

boolean canWrite(); 判断File对象所对应的目录或文件是否可写。

boolean canRead(); 判断File对象所对应的目录或文件是否可读。

boolean isFile(); 判断File对象所对应的是否是文件,而不是目录。

boolean isDirectory(); 判断File对象所对应的是否是目录,而不是文件。

boolean isAbsolute(); 判断File对象所对应的文件或目录是否是绝对路径。该方法消除了不同平台的差异,可以直接判断File对象是否为绝对路径。在UNIX/Linux/BSD等系统上,如果路径名开头是一条斜线(/),则表明该File对象对应一个绝对路径;在Windows等系统上,如果路径开头是盘符,则说明它是绝对路径。

3.获取常规文件信息

long lastModified(); 返回文件最后修改时间。

long length(); 返回文件内容的长度。

4.文件操作相关的方法

boolean createNewFile(); 当此File对象所对应的文件不存在时,该方法将新建的一个该File对象所指定的新文件,如果创建成功则返回true;否则返回false.(C)

boolean delete(); 删除File对象所对应的文件或路径。

static File CreateTempFile(String prefix,String suffix);在默认的临时文件目录创建一个临时空文件,使用给定前缀、系统生成的随机数和给定后缀作为文件名。这是一个静态方法,可以直接通过File来调用。preFix参数必须至少是3个字节长。建议前缀使用一个短的、有意义的字符串。建议前缀使用一个短的、有意义的字符串,比如”hjb“ 或”main”. suffix参数可以为null,在这种情况下,将使用默认的后缀”.tmp”.

static File CreateTempFile(String prefix,String suffix,File directory);在directory所指定的目录中创建一个临时空文件,使用给定前缀、系统生成的随机数和给定后缀作为文件名。这是一个静态方法,可以直接通过File来调用。

void deleteOnExit(); 注册一个删除钩子,指定当Java虚拟机退出时,删除File对象随对应的文件和目录。

5.目录操作相关方法(D)

boolean mkdir(); 试图创建一个File对象所对应的目录,如果创建成功,则返回true;否则返回false. 调用该方法时File对象必须对应一个路径,而不是一个文件。

String[] list(); 列出File对象的所有子文件名和路径名,返回String数组。

File[] listFiles(); 列出File对象的所有子文件和路径,返回File数组。

static File[] listRoots(); 列出系统所有的根路径。这是一个静态方法,可以直接通过File类来调用。
1
2
基本上我们平常用到的都是非线程安全的集合类,因为要使线程安全,是要加锁来实现的,势必造成性能降低。如hashset、hashmap、arraylist、linkedlist、treemap、treeset、stringbulider等。
stringbuffer、vector、hashtable这些都是专用于多线程的,再者以concurrent(意为:同时发生的)为前缀的集合类大多是线程安全的。
1
2
3
4
5
Servlet的生命周期一般可以用三个方法来表示:
init():仅执行一次,负责在装载Servlet时初始化Servlet对象
service() :核心方法,一般HttpServlet中会有get,post两种处理方式。在调用doGet和doPost方法时会构造servletRequest和servletResponse请求和响应对象作为参数。
destory():在停止并且卸载Servlet时执行,负责释放资源
初始化阶段:Servlet启动,会读取配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,将ServletConfig作为参数来调用init()方法。所以选ACD。B是在调用service方法时才构造的
1
2
3
4
5
6
7
8
9
10
11
12
13
JAVA语言中定义了8种基本的数据类型,来保存变量。JAVA要求程序中的每一个变量都规定自己的类型。正因为如此,JAVA属于强类型语言,从而不同于JavaScript这样的弱类型脚本语言。

  下面我们来看看这8种类型:  
byte8位,最大存储数据量是255,存放的数据范围是-128~127之间。
short16位,最大数据存储量是65536,数据范围是-32768~32767之间。
int32位,最大数据存储容量是232次方减1,数据范围是负的231次方到正的231次方减1
long64位,最大数据存储容量是264次方减1,数据范围为负的263次方到正的263次方减1
float32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
double64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
boolean:只有truefalse两个取值。
char16位,存储Unicode码,用单引号赋值。
注:一个字节=8位。
所以,整型数据类型中,需要内存空间最多的是long
1
修饰一个方法被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 修饰一个静态的方法其作用的范围是整个静态方法,作用的对象是这个类的所有对象; 修饰一个代码块被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象; 修饰一个类其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
1
2
3
4
5
6
(1)throw是语句抛出一个异常,一般是在代码块的内部,当程序出现某种逻辑错误时由程序员主动抛出某种特定类型的异常
(2)当某个方法可能会抛出某种异常时用于throws 声明可能抛出的异常,然后交给上层调用它的方法程序处理
(3)throws出现在方法函数头;而throw出现在函数体.throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
(4)如果try快中抛出了一个在catch子句中说明的异常类,那么程序将跳过try语句的其余代码,执行catch子句中的处理器代码。
(5)如果方法中的任何代码抛出了一个在catch子句中都有声明的异常类型,那么方***立即退出。
(6)无论是否抛出异常finally语句块最终都会执行。
1
2
3
4
5
6
7
比如表达式
byte a=2;
a=a-10
由于10是整型int,因此表达式a-10;将自动转换成int类型,int类型在赋值给byte,会编译错误
byte a=2;
a-=10;
不会发生编译错误,因为复合运算符是一个带有隐式转换的运算符,将右侧表达式类型自动转换成左侧表达式类型
1
2
3
4
5
6
7
8
9
10
成员变量和局部变量的区别
1、成员变量是独立于方法外的变量,是类的方法中的变量
1)、成员变量:包括和,用static修饰的是,不用static修饰的是,所有类的成员变量可以通过this来引用。
2)、局部变量:包括形参,方法局部变量,代码块局部变量,存在于方法的参数列表和方法定义中以及代码块中。
2、成员变量可以被public,protect,privatestatic等修饰符修饰,而局部变量不能被控制修饰符及 static修饰;两者都可以定义成final型。
3、成员变量存储在堆,局部变量存储在栈。局部变量的作用域仅限于定义它的方法,在该方法的外部无法访问它。成员变量的作用域在整个类内部都是可见的,所有成员方法都可以使用它。如果允许,还可以在类的外部使用成员变量。
4、局部变量的生存周期与方法的执行期相同。当方法执行到定义局部变量的语句时,局部变量被创建;执行到它所在的作用域的最后一条语句时,局部变量被销毁。类的成员变量,如果是实例成员变量,它和对象的生存期相同。而的生存期是整个程序运行期。
5、成员变量在累加载或实例被创建时,系统自动空间,并在分配空间后自动为成员变量指定初始化值,初始化值为默认值,基本类型的默认值为0,复合类型的默认值为null。(被final修饰且没有static的必须显式赋值),局部变量在定义后必须经过显式初始化后才能使用,系统不会为局部变量执行初始化。
6、局部变量可以和成员变量 同名,且在使用时,局部变量具有更高的优先级,直接使用同名访问,访问的是局部变量,如需要访问成员变量可以用this.变量名访问
本例中i为成员变量,有默认的初始值,如果定义在方法内部,就没有初始值
1
2
3
编译器将Java源代码编译成字节码class文件
类加载到JVM里面后,执行引擎把字节码转为可执行代码
执行的过程,再把可执行代码转为机器码,由底层的操作系统完成执行。
1
2
3
4
5
6
7
本题易错点是A选项,volatile关键字对任意单个volatile变量的的读写操作可以保证原子性,但类似于volatile++这种复合操作就无法保证原子性了。如果需要对这种复合操作保证原子性,最好用synchronized关键字。即synchronized保证三大性,原子性,有序性,可见性,volatile保证有序性,可见性,不能保证原子性。

B选项,为了实现volatile的内存语义,编译器在生成字节码时会在指令序列中插入内存屏障来禁止特定类型的处理器重排序,以此来保证有序性。

C选项,可见性是指当多个线程并发访问共享变量时,一个线程对共享变量的修改,其它线程能够立即看到。对于一个volatile变量的读,总是能看到对这个volatile变量最后的写入,保证了可见性。

D选项为干扰选项。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
以前我是堆,你是栈

你总是能精准的找到我,给我指明出路

后来有一天我明白了

我变成了栈,你却隐身堆海

我却找不到你了,空指针了

我不愿意如此,在下一轮full gc前

我找到了object家的finalize

又找到了你,这次我不会放手

在世界重启前,一边躲着full gc一边老去
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
在Java中,可以将一个类定义在另一个类里面或者一个方法里边,这样的类称为内部类,广泛意义上的内部类一般包括四种:成员内部类,局部内部类,匿名内部类,静态内部类 。

1.成员内部类

1)该类像是外部类的一个成员,可以无条件的访问外部类的所有成员属性和成员方法(包括private成员和静态成员);

2)成员内部类拥有与外部类同名的成员变量时,会发生隐藏现象,即默认情况下访问的是成员内部类中的成员。如果要访问外部类中的成员,需要以下形式访问:【外部类.this.成员变量  或  外部类.this.成员方法】;

3)在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问;

4)成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象;

5)内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。如果成员内部类用private修饰,则只能在外部类的内部访问;如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。外部类只能被public和包访问两种权限修饰。

2.局部内部类

1)局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内;

2)局部内部类就像是方法里面的一个局部变量一样,是不能有publicprotectedprivate以及static修饰符的。

3.匿名内部类

1)一般使用匿名内部类的方法来编写事件监听代码;

2)匿名内部类是不能有访问修饰符和static修饰符的;

3)匿名内部类是唯一一种没有构造器的类;

4)匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

4.内部静态类

1)静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似;

2)不能使用外部类的非static成员变量或者方法。
1
2
3
4
5
HashMap和Hashtable都是典型的Map实现,选项A正确。

Hashtable在实现Map接口时保证了线程安全性,而HashMap则是非线程安全的。所以,Hashtable的性能不如HashMap,因为为了保证线程安全它牺牲了一些性能。因此选项B错误

Hashtable不允许存入null,无论是以null作为key或value,都会引发异常。而HashMap是允许存入null的,无论是以null作为key或value,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Collection

-----List

-----LinkedList 非同步

----ArrayList 非同步,实现了可变大小的元素数组

----Vector 同步

-----Set 不允许有相同的元素

Map

-----HashTable 同步,实现一个key--value映射的哈希表,key和value都不允许出现null值

-----HashMap 非同步,

-----WeakHashMap 改进的HashMap,实现了“弱引用”,如果一个key不被引用,则被GC回收
注:
List接口中的对象按一定顺序排列,允许重复
Set接口中的对象没有顺序,但是不允许重复
Map接口中的对象是key、value的映射关系,key不允许重复
1
Java参数,不管是原始类型还是引用类型,传递的都是副本(有另外一种说法是传值,但是说传副本更好理解吧,传值通常是相对传址而言)。 如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的 值不会改变原始的值. 如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的 值,那么在函数内的改变会影响到传入的参数。如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的 地址,所以不会改变参数的值。
1
2
3
4
5
6
7
8
堆可以分为两部分:新生代,老年代。
新生代:1/3的堆空间 老年代:2/3的堆空间
而新生代可以细分:8/10的Eden区。2/10的Survivor区
Suivivor又可以细分为From区和To区,各占一半。

注意:
1.永久代MetaData在jdk1.8之前属于堆,现在属于物理内存,与堆完全隔开了
2.方法区只是逻辑概念,MetaData永久代和元空间是实实在在存在的,不能混为一体,元空间是方法区的具体实现。
1
静态方法的使用不依靠对象,只看类型,在编译时就确定了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
application对象是共享的,多个用户共享一个,以此实现数据共享和通信

JSP内置对象和属性列举如下:
1.request对象
     客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。
2.response对象
     response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。
3.session对象
     session对象指的是客户端与服务器的一次会话,从客户连到服务器的一个WebApplication开始,直到客户端与服务器断开连接为止。它是HttpSession类的实例.
4.out对象
     out对象是JspWriter类的实例,是向客户端输出内容常用的对象
5.page对象
     page对象就是指向当前JSP页面本身,有点象类中的this指针,它是java.lang.Object类的实例
6.application对象
     application对象实现了用户间数据的共享,可存放全局变量。它开始于服务器的启动,直到服务器的关闭,在此期间,此对象将一直存在;这样在用户的前后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作;在任何地方对此对象属性的操作,都将影响到其他用户对此的访问。服务器的启动和关闭决定了application对象的生命。它是ServletContext类的实例。
7.exception对象
   exception对象是一个例外对象,当一个页面在运行过程中发生了例外,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象
8.pageContext对象
pageContext对象提供了对JSP页面内所有的对象及名字空间的访问,也就是说他可以访问到本页所在的SESSION,也可以取本页面所在的application的某一属性值,他相当于页面中所有功能的集大成者,它的本 类名也叫pageContext。
9.config对象
config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)
1
父类的静态代码块 子类的静态代码块 父类的普通代码块 父类的构造方法 子类的普通代码块 子类的构造方法
1
2
3
4
不会初始化子类的几种
1. 调用的是父类的static方法或者字段
2.调用的是父类的final方法或者字段
3. 通过数组来引用
1
new URL()时必须捕获检查异常,但这个异常是由于字符串格式和URL不符导致的,与网址是否存在无关。URL的toString方法返回字符串,无论网址是否存在。
1
2
服务器端,首先是服务器初始化Socket,然后是与端口进行绑定(blind()),端口创建ServerSocket进行监听(listen()),然后调用阻塞(accept()),等待客户端连接。
与客户端发生连接后,会进行相关的读写操作(read(),write()),最后调用close()关闭连接。博客上看的,不知道全面不全面,大神轻喷。
1
2
3
4
5
6
7
8
9
1.clone():创建并返回此对象的一个副本。
2.equals(Object obj):指示一个对象是否与此对象"相等"。
3.finalize():当垃圾回收器确定不存在该对象的引用时,有对象的垃圾回收器进行调用,可以人工调用,但是不确定什么时候执行。
4.getClass():返回此Object的运行时的类。
5.hashCode():返回该对象的哈希码值,此方法是为了提高哈希表的性能。
6.notify():唤醒在此对象监视器上等待的单个线程。
7.notifyAll():则是唤醒在此对象监视器上等待的所有线程。
8.toString():返回该对象的字符串表示。
9.wait():在其他线程调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待。
1
散列表之开放定址法 在前面的文章中我们介绍过《散列表之链接法》,在链接法中,如果不同键值却将有相同的映射值,即有不同键值的元素却映射到散列表中的同一位置,那么就采用链表的方法,将映射到同一位置的元素插入到同一个链表之中,当需要删除, 查询元素时,只需要遍历该链表即可,链接法在最坏情况下删除和查询元素的时间代价为O(n)O(n) 今天我们来讲散列表中另外一种解决冲突的方法,那就是开放定址法(open addressing)。 假如你在外面旅游时,吃坏东西,急需上厕所,当你好不容易找到一件洗手间的时候,发现排了好多人,这时你会怎么做? 如果是链接法:排队不就行了,我就在外面等,迟早会排到我的 如果是开放定址法:直接放弃现有厕所,去寻找新的厕所 没错,放弃已被占用的位置,寻找新的插入位置就是开放定址法的思想,开放定址法中的开放二字指的是没有被占用的位置,定址指的是确定位置。开放定址法中,所有的元素都放在散列表中(链接法放在链表中)。也就是说散列表中的每一个位置,要么有元素,要么没有元素。当需要删除,查询元素时,我们从某一个位置开始,按照某种特定的确定下一个位置的方法来检查所有表项,直到找到目标元素,或者没有找到。
1
构造函数的作用是完成对象的初始化。当程序执行到new操作符时, 首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化。而选项B、D中,对象的初始化并不是通过构造函数完成的,而是读取别的内存区域中的对象的各个域来完成。
1
2
3
4
5
6
7
1. java.awt:提供了绘图和图像类,主要用于编写GUI程序,包括按钮、标签等常用组件以及相应的事件类。
2. java.lang:java的语言包,是核心包,默认导入到用户程序,包中有object类,数据类型包装类,数学类,字符串类,系统和运行时类,操作类,线程类,错误和异常处理类,过程类。
3. java.io:包含提供多种输出输入功能的类。
4. java.net: 包含执行与网络有关的类,如URL,SCOKET,SEVERSOCKET等。
5. java.applet:包含java小应用程序的类。
6. java.util:包含集合框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组、日期Date类、堆栈Stack类、向量Vector类等)。集合类、时间处理模式、日期时间工具等各类常用工具包。
7. java.sql:提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。

image-20230518090644092

1
2
3
4
三元操作符类型的转换规则:
1.若两个操作数不可转换,则不做转换,返回值为Object类型
2.若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换,int类型转换为long类型,long类型转换为float类型等 3.若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么,若数字S在T的范围内,则转换为T类型;若S超出了T类型的范围,则T转换为S类型。
4.若两个操作数都是直接量数字,则返回值类型为范围较大者
1
Object a = true ? new Boolean(false) : new Character('1').getClass(); // java.lang.Boolean Object b = true ? new Byte((byte) 1) : new Character('1'); // java.lang.Integer Object c = true ? new Byte((byte) 1) : new Short((short) 1); // java.lang.Short
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
兄弟们,记得住吗?
byte b = 1;
char c = 1;
short s = 1;
int i = 1;

// 三目,一边为byte另一边为char,结果为int
// 其它情况结果为两边中范围大的。适用包装类型
i = true ? b : c; // int
b = true ? b : b; // byte
s = true ? b : s; // short

// 表达式,两边为byte,short,char,结果为int型
// 其它情况结果为两边中范围大的。适用包装类型
i = b + c; // int
i = b + b; // int
i = b + s; // int

// 当 a 为基本数据类型时,a += b,相当于 a = (a) (a + b)
// 当 a 为包装类型时, a += b 就是 a = a + b
b += s; // 没问题
c += i; // 没问题

// 常量任君搞,long以上不能越
b = (char) 1 + (short) 1 + (int) 1// 没问题
// i = (long) 1 // 错误
1
2
3
4
5
6
7
1.抽象类可以有构造方法,接口中不能有构造方法。 
2.抽象类中可以有普通成员变量,接口中没有普通成员变量 
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。 
4.抽象类中的抽象方法的访问类型可以是publicprotected和(默认类型,虽然  eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。 
5.抽象类中可以包含静态方法,接口中不能包含静态方法 
6.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。 
7.一个类可以实现多个接口,但只能继承一个抽象类。 
1
2
3
static修饰的为类成员,会随着类的加载而加载,比如静态代码块,静态成员,静态方法(这里只是加载,并没有调用)等等,可以想象一下,如果把一个Class文件中的外部类设为static,目的难道是让这个类随着应用的启动而加载吗?如果在这次使用过程中根本没有使用过这个类,那么是不是就会浪费内存。这样来说设计不合理,总而言之,设计不合理的地方,Java是不会让它存在的。
而为什么内部类可以使用static修饰呢,因为内部类算是类的成员了,如果没有使用静态来修饰,那么在创建内部类的时候就需要先有一个外部类的对象,如果我们一直在使用内部类,那么内存中就会一直存在外部类的引用,而我们有时候只需要使用内部类,不需要外部类,那么还是会浪费内存,甚至会造成内存溢出。使用static修饰内部类之后,内部类在创建对象时就不需要有外部类对象的引用了。
最终结论就是:static可以用来修饰内部类,但是不可以用来修饰外部类
1
2
run()相当于线程的任务处理逻辑的入口方法,它由Java虚拟机在运行相应线程时直接调用,而不是由应用代码进行调用。
start()的作用是启动相应的线程。启动一个线程实际是请求Java虚拟机运行相应的线程,而这个线程何时能够运行是由线程调度器决定的。start()调用结束并不表示相应线程已经开始运行,这个线程可能稍后运行,也可能永远也不会运行。
1
2
3
4
5
hashCode方法本质就是一个哈希函数,这是Object类的作者说明的。Object类的作者在注释的最后一段的括号中写道:将对象的地址值映射为integer类型的哈希值。但hashCode()并不完全可靠的,有时候不同的对象他们生成的hashcode也会一样,因此hashCode()只能说是大部分时候可靠。
因此我们也需要重写equals()方法,但因为重写的equals()比较全面比较复杂,会造成程序效率低下,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。因此,正常的操作流程是先用hashCode()去对比两个对象,如果hashCode()不一样,则表示这两个对象肯定不相等,直接返回false,如果hashCode()相同,再对比他们的equals()。
综上所述:
equals()相等的两个对象hashCode()一定相等。
hashCode()相等的两个对象equal()不一定相等。
1
String split 这个方法默认返回一个数组, 如果没有找到分隔符, 会把整个字符串当成一个长度为1的字符串数组返回到结果, 所以此处结果就是1
1
既然是实现接口,就要实现接口的所以方法,相当于重写方法,方法的重写需要满足:三同一大一小(方法名、返回值类型、形参相同;访问权限>=重写前;抛出异常<=重写前)
1
switch支持 int及以下(charshortbyte),String, Enum

image-20230526173031485

image-20230526173038011

1
2
出现多个catch块时,应该先处理小异常,再处理大异常,也就是将处理父类异常的catch块放在处理子类异常的catch块之后。
Exception是所有异常的父类,如果处理Exceptioncatch语句块放在前面,会导致任何异常在这个catch块都能被匹配,后续catch块将变得没有意义。
1
2
3
4
当一个类的一个或多个方法是抽象方法时
当类是一个抽象类的子类,并且不能为任何抽象方法提供任何实现细节或方法体时
当一个类实现一个接口,并且不能为任何抽象方法提供实现细节或方法体时
该类一定为抽象类
1
2
3
4
5
6
int 是八大基本数据类型之一(byte,char,short,int,long,float,double,boolean
Integer 是 int 包装类;
int是基本数据类型,默认值为0,
Integer 是类,默认值为null
Integer 表示的是对象,用一个引用指向这个对象
int是基本数据类型,直接存储数值。
1
2
3
4
String重写后的equals底层源码:
1、判断比较的内容是否为Object对象
2、判断是否为String对象
符合以上条件才能开始比较,否则直接返回false,所以拿String字符串对象 equals char数组对象,结果一定为false
1
2
3
4
5
6
7
Spring 支持 7 种事务传播行为:
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。
1
事务的传播性一般用在事务嵌套的场景,比如一个事务方法里面调用了另外一个事务方法,那么两个方法是各自作为独立的方法提交还是内层的事务合并到外层的事务一起提交,这就是需要事务传播机制的配置来确定怎么样执行。
1
2
3
checked exception:指的是编译时异常,该类异常需要本函数必须处理的,用try和catch处理,或者用throws抛出异常,然后交给调用者去处理异常。
runtime exception:指的是运行时异常,该类异常不必须本函数必须处理,当然也可以处理。
Thread.sleep()抛出的InterruptException属于checked exception;IllegalArgumentException属于Runtime exception;
1
2
3
4
A.文件分为文本文件和二进制文件,计算机只认识二进制,所以实际上都是二进制的不同解释方式。文本文件是以不同编码格式显示的字符,例如AsciiUnicode等,window中文本文件的后缀名有".txt",".log",各种编程语言的源码文件等;二进制文件就是用文本文档打开是看不懂乱码,只要能用文本打开的文件都可以算是文本文件,只是显示的结果不是你想要的,二进制文件只有用特殊的应用才能读懂的文件,例如".png",".bmp"等,计算机中大部分的文件还是二进制文件。
B.File类是对文件整体或者文件属性操作的类,例如创建文件、删除文件、查看文件是否存在等功能,不能操作文件内容;文件内容是用IO流操作的。
C.当输入过程中意外到达文件或流的末尾时,抛出EOFException异常,正常情况下读取到文件末尾时,返回一个特殊值表示文件读取完成,例如read()返回-1表示文件读取完成。
D.上面A选项已经说了,不论是文本文件还是二进制文件,在计算机中都是以二进制形式存储的,所以都当做二进制文件读取。
1
2
数组长度在创建时就确定了,要改变数组长度只能重新创建新的数组,将原有数组复制到新的数组之中。
这也是ArrayList扩容时候的效率低于LinkedList的原因。

image-20230609220413734

1
2
3
4
5
6
7
8
9
下面的方法可用在 Servlet 程序中读取 HTTP 头。这些方法通过 HttpServletRequest 对象可用:
1Cookie[] getCookies()
返回一个数组,包含客户端发送该请求的所有的 Cookie 对象。
2Object getAttribute(String name)
以对象形式返回已命名属性的值,如果没有给定名称的属性存在,则返回 null
3String getHeader(String name)
以字符串形式返回指定的请求头的值。Cookie也是头的一种;
4String getParameter(String name)
以字符串形式返回请求参数的值,或者如果参数不存在则返回 null
1
2
3
4
5
6
7
8
9
10
11
HttpServlet容器响应Web客户请求流程如下:
1)Web客户向Servlet容器发出Http请求;
2)Servlet容器解析Web客户的Http请求;
3)Servlet容器创建一个HttpRequest对象,在这个对象中封装Http请求信息;
4)Servlet容器创建一个HttpResponse对象;
5)Servlet容器调用HttpServlet的service方法,这个方法中会根据request的Method来判断具体是执行doGet还是doPost,把HttpRequestHttpResponse对象作为service方法的参数传给HttpServlet对象;
6)HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;
7)HttpServlet调用HttpResponse的有关方法,生成响应数据;
8)Servlet容器把HttpServlet的响应结果传给Web客户。

doGet()doPost() 是创建HttpServlet时需要覆盖的方法.
1
通过ServletConfig接口的getInitParameter(java.lang.String name)方法 ServletContext对象:servlet容器在启动时会加载web应用,并为每个web应用创建唯一的servlet context对象,可以把ServletContext看成是一个Web应用的服务器端组件的共享内存,在ServletContext中可以存放共享数据。ServletContext对象是真正的一个全局对象,凡是web容器中的Servlet都可以访问。    整个web应用只有唯一的一个ServletContext对象 servletConfig对象:用于封装servlet的配置信息。从一个servlet被实例化后,对任何客户端在任何时候访问有效,但仅对servlet自身有效,一个servlet的ServletConfig对象不能被另一个servlet访问。
1
常见的代码优化技术:复写传播(代码外提)、删除死代码、强度削弱、归纳变量删除
1
setDaemon()可以把线程设置为守护线程(也叫精灵线程,后台线程),它必须在线程启动前调用。

image-20230609220455513

1
java源文件的后缀名是.java。源文件通过jvm虚拟机编译后会生成二进制字节码文件,后缀是.class
1
java的基本编程单元是类,基本存储单元是变量。

image-20230609220519656

img


牛客-刷题
https://test.atomgit.net/blog/2023/04/09/牛客-刷题/
作者
Memory
发布于
2023年4月9日
更新于
2023年12月22日
许可协议