byte 字节 == 8bit
bit 位,比特
float == 8byte == 64bit
int == 4 byte
byte == 1 byte(基本数据类型中,byte占据1个byte字节)
short == 2 byte
char == 2 byte
TCP Socket服务器端流程 :
服务器初始化socket,然后与端口进行绑定(bind),然后进行监听,表示愿意接受连接,然后执行阻塞方法accept()知道接收到connect()请求,然后进行read()和write(),然后close
TCP Socket客户端端流程 :
初始化socket(),然后调用connect()请求连接,然后进行read()和write(),然后close()
Thread的run()方法,如果Thread类中的target(也就是Runnable对象)为空的话,那么run方法什么都不执行
new Thread().start(); 会执行一个空的run()方法
target的赋值,是通过构造函数,调用init()方法来对target进行设置的
Thread的start方法,是一个同步方法,是通过调用一个native方法 start0()来调用run()方法的
同步方法与同步代码块之间的区别:
同步方法:(粗粒度锁)
普通方法:public synchronized void test(){} : 获取的是当前方法的调用对象的this的锁
静态方法:public static synchronized test(){}; 获取的是方法所在类的字节码上的锁
同步代码块(细粒度锁):
synchronized(obj){}: 其中obj可以自己指定,可以是任意对象
Test对象和TestB对象都没有重写Object中的equals()方法,也就是说,会调用Object中的equals方法
Object中的equals方法: obj1.equals(obj2),会直接判断obj1==obj2,返回这个结果
Collection的补充:
SortedSet,实现了Set接口(接口,无所谓是不是同步的)
TreeSet,通过实现NavigableSet,从而间接的实现SortedSet(文档中说,TreeSet不是线程同步的)
EnumSet,不是线程同步的,继承了Enum类
Collection,除了包括Set,List,还包括Queue
Queue包括常见的Deque接口(双端队列)和PriorityQueue(优先队列,不是线程同步的),ArrayDeque实现了Deque接口,不是线程同步的
LinkedList实现List接口的同时,实现了Deque接口,说明LinkedList是一个双端队列
ArrayList实现了RandomAccess,支持随机访问
LinkedList没有实现RandomList,无法随机访问
java中的按值传递和按引用传递的区别:
对于引用,比如Object obj = new Object1();
obj其实是一个地址值,这个地址值可以说是指向Object1,也可以说是obj的值就是Object1的地址值
这样,java中传参,不管传的参数,是不是引用类型的,都可以理解为是按值传参,因为按引用传参,传递引用其实也就是一个目标对象的地址,或者说指向目标对象的指针.
按引用传递
Object obj = new Object1();
比如method(obj){ obj.changeValue();} 那么将会改变Object1对象
按值传递
int number = 1; 比如method2(number){ number = 2; },原number还是1
如果参数传的是数组,不管是基本类型数组,还是对象类型数组,都属于按引用传递
例如: method3(int[] a)
或者: method3(Object[] a)
| 与 || 的区别:
|与|| 都是进行 || 判断, 但区别在于, | (非短路或) 在前面的表达式为真的时候,依旧会执行后面的表达式, 而 || (短路或) 不会执行后面的表达式
& 与 && 的区别:
与| 与 || 的区别同理, & 非短路, 即使前面的表达式为假,依旧会执行后面的表达式,而&& 不会执行后面的表达式
按值传递,与按引用传递:
StringBuffer A 的A.append(StringBuffer B)的方法,就是将B中的char[]中的值,附加到A的char[]中,使用的是System.Arraycopy()方法,其间会对A进行扩容
StringBuffer a = new StringBuffer("A");
StringBuffer b = new StringBuffer("B");
对于operator(StringBuffer x,StringBuffer y),传入operator(a,b)
传入对象,相当于传入另一把原对象的钥匙:
x.append(y); 会将原对象x改变,
y = x; 是将原本指向StringBuffer("B")对象的钥匙,有指向了别的对象(x,即StringBuffer("B"),而调用函数中的StringBuffer b ,仍然指向StringBuffer("B"),没有改变,所以在调用函数中,println(b),仍然是"B",而StringBuffer a 所指向的对象,已经被改变了,变成了"AB"
StringBuffer b = new StringBuffer("B");
中的内存状态为:(左边为运行时栈,右边为堆)
wait后,某线程调用obj的wait方法,会导致此线程放弃obj锁,并且进入obj的等待锁定池,只有此对象发出notify()或者notifyAll()方法,本线程才会获得锁(如果有多个线程同时等待这个锁,那么这几个线程需要竞争这个锁,但是一定有一个线程会获得这个锁),获得这个锁之后,获得锁的线程会进入就绪状态,等待CPU调度运行此线程,而不是直接进入运行态
sleep会暂停线程,但是不会释放锁, 是让线程停止执行指定的时间,把CPU的执行时间留给其他线程,但是监控状态依然保持,到时后会自动恢复执行
wait,notify,notifyAll 都必须在synchronized的保护下执行,而且必须是notify的对象作为synchronized的锁
wait,sleep 都会抛出InterruptedException
sleep 和 wait都需要捕获InterruptedException:
public final void wait() throws InterruptedException {
wait(0);
}
public final native void wait(long timeout) throws InterruptedException;
public static native void sleep(long millis) throws InterruptedException;
Servlet是一个接口, javax.servlet.Serlvet
service是在Servlet中最初定义的,最终由Servlet实现类如HttpServlet最终实现,service中,主要是判断请求的类型,然后调用对应的doGet/doPost/doPut等方法
GenericServlet是一个抽象类,只实现了部分方法, 没有实现service方法
无论是get过来的请求,还是put请求,或者post请求,都是在service中处理,然后分发到对应的方法中
get请求,就是METHOD GET,post请求,就是METHOD_PUT请求,以此类推
<<深入理解java虚拟机>> 中P66页:
要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析之后,发现没有与GC Root相连,那么就会被第一次标记,第一次标记完,会进行一次finalize()筛选,看是否有比较执行对象的finalize()方法,这个finalize()方法,就是对象的唯一一次拯救机会,如果没有执行finalize()方法,那么就会直接进入回收队列,如果执行finlize()方法,那么还可以使用此方法进行拯救:
判断是否有必要执行finalize()方法:
如果对象没有覆盖Object的finalize()方法,或者此对象的finalize()方法已经被JVM调用过一次, 就不会在执行此对象的finalize()方法,那么,此对象就会被回收
进入了"Dead"状态的线程, 不一定就会被回收,如果override了finalize()方法,还可以拯救
PROPAGATION_SUPPORTS:表示该方法不需要运行在一个事务中,但是如果当前存在一个事物,那么也支持SUPPORTS此方法运行在次事务中
PROPATATION_REQUIRED:表示该方法需要REQUIRED运行在一个事务中,如果当前存在事务,就运行在此事务中,如果不存在事务,就创建一个新的事物
PROGATATION_REQUIRES_NEW: 表示此方法需要运行在一个新的事务中,如果存在当前事务,则将当前事务挂起,并将方法运行在一个新的NEW事务中
PROPAGATION_NOT_SUPPORTED:表示当前方法不支持事务,如果存在当前事务,则将当前事务挂起,不抛出异常
PROGATATION_NEVER:表示方法不能运行在事务中,如果存在当前事务,则抛出异常,而PROGATION_NOT_SUPPORT不抛出异常
PROPAGATION_MANDATORY: 表示方法强制运行在事务中,如果存在不存在当前事务,就抛出异常,PROPAGATION_REQUIRED方法也是必须运行在事务中,但是不会抛出异常,而是新建一个事务
PROPATATION_NESTED: 表示如果当前方法应该执行嵌套(NESTED)事务,也就是,支持当前事务,增加savepoint点,与当前事务同步提交或者回滚
只有MANDATORY和NEVER才会抛出异常,
SUPPORT,REQUIRED不会抛出异常,
java提供的事件处理模型是一种人机交互模型,包括三个基本要素:
事件源:事件发生的场所,指各个组件,如按钮等,点击按钮就是组件上发生的一个事件
事件:事件封装了组件上发生的事情,如按钮单击,按钮放开等
事件监听器: 负责监听事件源上发生的事件,同时负责处理事件
f1与f2,表示float,同时也指向float[]数组中的第一个元素,因此f1==f2是可以比较的
题中f1第一个元素为42.0f,而f2第一个元素为0,因此不相等
long x = 42, f1[0] == 42.0f ,
x == f1[0] ,两个类型不同的基本类型相比较,会转换成精度比较高的然后再进行比较,long与float比较,long会转换成float,因此x == f1[0]
f1与f3都是float[],且指向同一数组,所以f1==f3
虽然f1和f2,f3都是数组指针,都可以之想数组中的第一个元素,也可以进行f1==f3 的比较
但是要注意:
== 两侧,必须是同一数据类型,不能出现float[] f1 ; float f ; f1==f的情况,即使f1的第一元素与f局有相同的值,也不行
call by value 指的是按值传递
call by reference 指的是按引用传递
java中方法中的参数,称为形式参数,简称形参,
调用函数中传入method中的原参数,称为实际参数,简称实参
实际参数的参考地址,指的是实际参数所指向对象的地址
实际参数的内容,指的是实际参数所指向的对象的内容
java 中,无论传递的是基本数据类型,还是引用数据类型,传递的是实际参数的副本,
如果是基本数据类型,就是按值传递(call by value),method()中的形参就是实参的一个副本,方法中无论怎么改变这个副本的值,都不会影响实际基本类型参数的值
如果是对象(引用类型),就是按引用传递(call by reference),但是传递到method之后,method()的形参,相当于创建了一个指向与实参相同对象的一个钥匙副本
OutputStream,和InputStream,属于"自己" 与 File之间的数据沟通,input和output都是相对于自己来说的:
如果是FileOutputStream,就是相对于自己输出(output),也就是向File中写入数据
如果是FileInputStream,就是相对于自己输入(input),也就是从File中读出数据
PrintWriter是将一个对象以格式化的方式打印出来,不涉及到写入文件中,虽然可以传入Object,但是只是调用了object.toString方法,将object打印出来