- ArralList的
remove
方法,在去掉一个元素的时候,会自动的对列表中的剩余元素重新排序。
例如:
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.remove(1); // list从1、2、3、4变成1、3、4
list.remove(1); // list从1、3、4变成1、4
- 可变参数方法的每次调用都会导致进行一次数组分配和初始化。
在重视性能的情况下,可以采取一种模式:假设可以确定对某个方法95%的 调用会有3个或者更少的参数,就声明该方法的5个重载,当参数的数目超过3个时,就是使用一个可变参数方法。
例如:
public void foo(){}
public void foo(int a1){}
public void foo(int a1, int a2){}
public void foo(int a1, int a2, int a3){}
public void foo(int a1, int a2, int a3, int... rest){}
Effective Java(第二版)
- 首先java文件编译生成class文件其基本规则是这样的:
内部类的class文件命名是:主类+$+内部类名
匿名类的class文件命名是:主类+$+(1,2,3....)
Effective Java(第二版)
- 对于任何需要精度答案的计算,不要使用float或者double。如果涉及的数值不大,可以使用int或者long,不过最好还是使用BigDecimal。
数值范围不超过9位十进制数字,可以使用int。
数值范围不超过18位数字,可以使用long。
超过18位数字,就必须使用BigDecimal。
Effective Java(第二版)
- 装箱基本类型的几种合理用处:
- 作为集合中的元素、键和值。你不能将基本类型放在集合中,因此必须使用装箱基本类型。
- 在参数化类型中,必须使用装箱基本类型作为类型参数,因为Java不允许使用基本类型。
- 在进行反射的方法调用时,必须使用装箱基本类型。
Effective Java(第二版)
<? extends T>
和<? super T>
,在初始化的时候是可以赋值子类或者父类的对象。
例如:
List<? extends Animal·> carList = new ArrayList<Cat>(); // Cat是Animal的子类,该语句是允许的。
carList.add(new SmallCat()); // SmallCat是Cat的子类,但是该语句会报错,无法编译。
try-catch-finally
:
- 当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;
- 当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;
-
Volatile
变量具有synchronized
的可见性特性,但是不具备原子特性。这就是说线程能够自动发现volatile
变量的最新值。- 正确使用 volatile 变量的条件
您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
- 对变量的写操作不依赖于当前值。
- 该变量没有包含在具有其他变量的不变式中。
- 实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态。
- 第一个条件的限制使
volatile
变量不能用作线程安全计数器。虽然增量操作(x++
)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使 x 的值在操作期间保持不变,而volatile
变量无法实现这点。(然而,如果将值调整为只从单个线程写入,那么可以忽略第一个条件。)
-
- java中接口定义的方法默认是
public abstract
修饰符。 - 接口不可以定义变量,只能定义常量,常量的默认修饰符是
public static final
,且必须赋初值。
- java中接口定义的方法默认是
- ecplise选中变量,相同变量名高亮快捷建:
alt+shift+o
- 浏览器只是将cookie的value和name发送给了服务器端,并没有cookie的属性(比如path、maxAge)放进去。因此在java Servlet中,从
HttpServletRequest
中通过getCookies()
获取的cookie,其getMaxAge()
方法总是返回-1。
https://stackoverflow.com/questions/14391749/in-java-servlet-cookie-getmaxage-always-returns-1
-
- Java 流在处理上分为字符流和字节流。字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。
- Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流和 java 内 Unicode 字符流之间的转换。而类 InputStreamReader 和 OutputStreamWriter 处理字符流和字节流的转换。字符流(一次可以处理一个缓冲区)一次操作比字节流(一次一个字节)效率高。
- 按数据格式分:
- 二进制格式(只要不能确定是纯文本的) : InputStream, OutputStream 及其所有带 Stream 结束的子类
- 纯文本格式(含纯英文与汉字或其他编码方式); Reader, Writer 及其所有带 Reader, Writer 的子类
JDK和JRE的区别是什么?
JRE顾名思义是java运行时环境,包含了java虚拟机,java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。
JDK顾名思义是java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:jconsole,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。
如果你需要运行java程序,只需安装JRE就可以了。如果你需要编写java程序,需要安装JDK。
JRE根据不同操作系统(如:windows,linux等)和不同JRE提供商(IBM,ORACLE等)有很多版本
java的跨平台不是java源程序的跨平台 ,如果是这样,那么所以语言都是跨平台的, java源程序先经过javac编译器编译成二进制的.class字节码文件(java的跨平台指的就是.class字节码文件的跨平台,.class字节码文件是与平台无关的),.class文件再运行在jvm上,java解释器(jvm的一部分)会将其解释成对应平台的机器码执行,所以java所谓的跨平台就是在不同平台上安装了不同的jvm,而在不同平台上生成的.class文件都是一样的,而.class文件再由对应平台的jvm解释成对应平台的机器码执行。 最后解释下机器码和字节码的区别: 一,机器码,完全依附硬件而存在~并且不同硬件由于内嵌指令集不同,即使相同的0 1代码 意思也可能是不同的~换句话说,根本不存在跨平台性~比如~不同型号的CPU,你给他个指令10001101,他们可能会解析为不同的结果~ 二,我们知道JAVA是跨平台的,为什么呢?因为他有一个jvm,不论那种硬件,只要你装有jvm,那么他就认识这个JAVA字节码~~~~至于底层的机器码,咱不用管,有jvm搞定,他会把字节码再翻译成所在机器认识的机器码~~~
两个数值进行二元操作时,会有如下的转换操作:
如果两个操作数其中有一个是double类型,另一个操作就会转换为double类型。
否则,如果其中一个操作数是float类型,另一个将会转换为float类型。
否则,如果其中一个操作数是long类型,另一个会转换为long类型。
否则,两个操作数都转换为int类型。
- java中,基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的。
- 静态变量只能在类主体中定义,不能在方法中定义
- 低级向高级是隐式类型转换,高级向低级必须强制类型转换,
byte<char<short<int<long<float<double
final String s = "a"; //注意:这里s用final修饰,相当于一个常量
String str5 = s + "b";
System.out.println(str5 == "ab");
1 栈中开辟一块空间存放引用s;
2 “a”先在字符串池里找,如果有则引用s指向String池中的“a”
3 s + “b”,因为s是被final修饰,相当于一个常量,所以改语句相当于”a” + “b”,查看String池是否有”ab”,没有则添加,并且str5指向它。
4 str5指向的对象在String池中的”ab”,所以输出为true。
String s1 = "a";
String s2 = "b";
String str6 = s1 + s2;
System.out.println(str6 == "ab");
1) 栈中开辟一块中间存放引用s1,s1指向池中String常量”a”,
2) 栈中开辟一块中间存放引用s2,s2指向池中String常量”b”,
3) 栈中开辟一块中间存放引用str5,
4) s1 + s2通过StringBuilder的最后一步toString()方法还原一个新的String对象”ab”,因此堆中开辟一块空间存放此对象,
5) 引用str6指向堆中(s1 + s2)所还原的新String对象,
6) str6指向的对象在堆中,而常量”ab”在池中,输出为false。
基础类型,如int、float、long的封装类,其valueOf方法是有缓存机制的,以int为例。
valueOf源码如下:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
当参数再-128到127时,会先到IntegerCache查找是否有缓存。而这个IntegerCache是和基础类型所共用的缓存池。
例如:
int i = 12;
Integer k = Integer.valueOf(12);
Integer j = new Integer(12);
1 创建变量i,先到IntegerCache中查找是否有12这个值,没有则创建并返回。
2 valueOf创建变量k,因为12再-128到127范围内,所以先从IntegerCache中查找,发现找到有12这个值,直接返回。所以k和i所引用的内存是一样的。k == i 返回true。
3 变量j的创建是直接new,所以无论IntegerCache中是否有对应的值,都会重新再堆中创建一个新的空间存放12。因此,j == i 返回false。
基本类型 | 装箱类型 | 取值范围 | 是否缓存 | 存范围 |
---|---|---|---|---|
byte | Byte | -128 ~ 127 | 是 | -128 ~ 127 |
short | Short | -2^15 ~ (2^15 - 1) | 是 | -128 ~ 127 |
int | Integer | -2^31 ~ (2^31 - 1) | 是 | -128 ~ 127 |
long | Long | -2^63 ~ (2^63 - 1) | 是 | -128~127 |
float | Float | – | 否 | – |
double | Double | – | 否 | – |
boolean | Boolean | true, false | 是 | true, false |
char | Character | \u0000 ~ \uffff | 是 | \u0000 ~ \u007f |
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。
反码的表示方法是:
正数的反码是其本身。
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
补码的表示方法是:
正数的补码就是其本身。
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)。
int i = 5;
int j = 10;
System.out.println(i + ~j);
10原码:0000000000000000,0000000000001010;
~10: 1111111111111111,1111111111110101 变为负数,计算机用补码存储
~10反码:10000000000000000,0000000000001010
~10补码:10000000000000000,0000000000001011,等于 -11
故程序结果-6
https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html
第7层应用层(Application Layer)
提供为应用软件而设的界面,以设置与另一应用软件之间的通信。例如:HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等。
第6层表达层(Presentation Layer)
把数据转换为能与接收者的系统格式兼容并适合传输的格式。
第5层会话层(Session Layer)
负责在数据传输中设置和维护电脑网络中两台电脑之间的通信连接。
第4层传输层(Transport Layer)
把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议义(TCP)等。
第3层网络层(Network Layer)
决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据。例如:互联网协议(IP)等。
第2层数据链接层(Data Link Layer)
负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成了帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。
分为两种子层:logic link control sublayer & media access control sublayer
第1层物理层(Physical Layer)
在局部局域网上传送帧,它负责管理电脑通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机适配器等
ApplicationContextAware作用:
https://my.oschina.net/liweigov/blog/63896
http://www.jianshu.com/p/4145f507f3e7
- Math类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英文名称的含义相对应。
- 例如,ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;
- floor的英文意义是地板,该方法就表示向下取整,Math.ceil(11.6)的结果为11,Math.ceil(-11.6)的结果是-12;
- 最难掌握的是round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
继承中的权限问题
如果父类是public,子类和父类不在一个包中,子类可以继承到父类中default权限的成员变量和成员函数,但是由于权限不够,无法使用。(之所以说子类可以继承,是因为编译报错不是找不到该成员,而是权限问题无法访问)。
如果父类是public,父类中的成员变量和成员函数是private,则只能在父类中使用它们。
SpringMVC之类型转换Converter(Conveter和Formatter)
非静态内部类不能有静态成员:
对于java类加载顺序我们知道,首先加载类,执行static变量初始化,接下来执行对象的创建,如果我们要执行代码中的变量i初始化,
那么必须先执行加载OuterClass,再加载Innerclass,最后初始化静态变量i,问题就出在加载Innerclass上面,我们可以把InnerClass看成OuterClass的非静态成员,它的初始化必须在外部类对象创建后以后进行,要加载InnerClass必须在实例化OuterClass之后完成 ,java虚拟机要求所有的静态变量必须在对象创建之前完成,这样便产生了矛盾。
静态内部类可以有静态成员:
我们可以把静态内部类作为外部类OuterClass的一个静态成员,在执行类加载过程中,静态内部类在加载OuterClass后会进行初始化,同样的原理,静态内部类的静态成员也将被初始化,进行内存的分配,注意到,这时无论是内部类还是外部类,对象都没有实例化,这也说明了非静态内部类为什么不能有静态成员的原因。
http://bbs.youkuaiyun.com/topics/390607261
匿名内部类指必须实现其他类或者接口,但不是说必须得实现抽象类或者接口,哪怕是普通类也可以实现,并且可以通过对其中的方法进行重写,重写要遵守的规则和普通类重写的规则相同。
http://blog.sina.com.cn/s/blog_105817120102vz0q.html
super.class()陷阱
子类中调用super.class().getName(),为什么不返回父类的类名,而是子类的类名?
因为super并没有代表超类的一个引用的能力,只是代表调用父类的方法而已。所以super.getClass()是表示调用父类的方法。getClass方法来自Object类,它返回对象在运行时的类型。因为在运行时的对象类型是Test,所以this.getClass()和super.getClass()都是返回Test。
此外,由于getClass()在Object类中定义成了final,子类不能覆盖该方法,所以,在test方法中调用getClass().getName()方法,其实就是在调用从父类继承的getClass()方法,等效于调用super.getClass().getName()方法,所以,super.getClass().getName()方法返回的也应该是Test。
如果想得到父类的名称,应该用如下代码:
getClass().getSuperClass().getName();
http://www.cnblogs.com/merru/articles/4632640.html
http://www.cnblogs.com/heima-jieqi/archive/2012/04/10/2440086.html
HTML中<style>
标签的作用和用法
<style>
标签用于为 HTML 文档定义样式信息。
在 style 中,您可以规定在浏览器中如何呈现 HTML 文档。
type 属性是必需的,定义 style 元素的内容。唯一可能的值是 text/css
。
http://www.w3school.com.cn/tags/tag_style.asp
http://www.w3school.com.cn/jsref/dom_obj_style.asp
CSS参考手册
http://www.runoob.com/cssref/css-reference.html
CSS属性
Flex布局:
Flex 是 Flexible Box 的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为 Flex 布局。
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称”项目”。
一般在HTML的<style>
标签中的display属性中设置为flex。
注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
http://www.ruanyifeng.com/blog/2015/07/flex-examples.html
z-index属性
z-index 属性指定一个元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。
http://www.runoob.com/cssref/pr-pos-z-index.html
try-catch-finally中return的执行顺序
http://qing0991.blog.51cto.com/1640542/1387200
抽象类是可以继承实体类,但前提是实体类必须有明确的并且可访问的构造函数。
如果继承的实体类的构造函数是私有的,那么编译不能通过。
http://blog.youkuaiyun.com/ckw1988/article/details/4639514
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。
http://blog.youkuaiyun.com/youjianbo_han_87/article/details/2586375
java 接口可以也只能继承多个接口
Interface3 Extends Interface0, Interface1, interface… // 这个是合法的
但是类不能继承多个类,因为一旦继承多个类,如果有个方法,多个父类中都有,那么无法知道到底该调用哪个类的方法。
而接口因为本身是抽象类的,并且接口的作用是用来定义一个行为。即使有多个接口的方法一样,我们在实现的时候,也只需要实现这一个方法即可,表明我们实现了这一个行为,并不需要区分这个行为到底是哪个接口提供的。
http://javaeedevelop.iteye.com/blog/1513135
常见的几种runtimeException:
NullPointerException - 空指针引用异常
ClassCastException - 类型强制转换异常。
IndexOutOfBoundsException - 下标越界异常
IllegalArgumentException - 传递非法参数异常
ArithmeticException - 算术运算异常
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
NegativeArraySizeException - 创建一个大小为负数的数组错误异常
NumberFormatException - 数字格式异常
SecurityException - 安全异常
UnsupportedOperationException - 不支持的操作异常
Count(1)和Count(*)性能对比
很多人说Count(*)最终会转换成Count(1),而SELECT COUNT(1)省略了转换的这一步,所以SELECT COUNT(1)效率更高。但其实这是错误的。
在Innodb该引擎下,COUNT(1)和COUNT()哪个快呢?结论是:这俩在高版本的MySQL(5.5及以后,5.1的没有考证)是没有什么区别的,也就没有COUN(1)会比COUNT()更快这一说了。
通常,我们将第一个字段(一般是ID)作为主键,那么这个时候COUNT(1)实际统计的就是行数,因为主键肯定是非NULL的。问题是Innodb是通过主键索引来统计行数的吗?结论是:如果该表只有一个主键索引,没有任何二级索引的情况下,那么COUNT()和COUNT(1)都是通过通过主键索引来统计行数的。如果该表有二级索引,则COUNT(1)和COUNT()都会通过占用空间最小的字段的二级索引进行统计,也就是说虽然COUNT(1)指定了第一列但是innodb不会真的去统计主键索引(一般为第一个字段的索引)。
https://zhuanlan.zhihu.com/p/28397595
mysql中where和having的区别
Where 是一个约束声明,使用Where约束来自数据库的数据,Where是在结果返回之前起作用的,Where中不能使用聚合函数,WHERE 子句作用于表和视图。
Having是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作,在Having中可以使用聚合函数。在查询过程中聚合语句(sum,min,max,avg,count)要比having子句优先执行。而where子句在查询过程中执行优先级高于聚合语句。
HAVING 子句作用于组,一般跟在group by之后,执行记录组选择的一部分来工作的。
http://blog.youkuaiyun.com/mark_lq/article/details/45012955
mysql查询-存在一个表而不在另一个表中的数据
A、B两表,找出ID字段中,存在A表,但是不存在B表的数据。A表总共13w数据,去重后大约3W条数据,B表有2W条数据,且B表的ID字段有索引。
方法一
使用 not in ,容易理解,效率低 ~执行时间为:1.395秒~
select distinct A.ID from A where A.ID not in (select ID from B)
方法二
使用 left join…on… , “B.ID isnull” 表示左连接之后在B.ID 字段为 null的记录 ~执行时间:0.739秒~
select A.ID from A left join B on A.ID=B.ID where B.ID is null
方法三
逻辑相对复杂,但是速度最快 ~执行时间: 0.570秒~
select * from B where (select count(1) as num from A where A.ID = B.ID) = 0
http://blog.youkuaiyun.com/u012732259/article/details/42215119
线程中sleep和wait的区别
sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行。
wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在notfiy方法后增加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。
http://www.cnblogs.com/DreamSea/archive/2012/01/16/2263844.html
CSS :hover
选择器
:hover
在鼠标移到链接上时添加的特殊样式。
:hover
选择器器可用于所有元素,不仅是链接。
http://www.runoob.com/cssref/sel-hover.html
HTML中id、name、class 区别
http://blog.youkuaiyun.com/ithomer/article/details/8080912
pageEncoding和contentType的关系:
(1). pageEncoding的内容只是用于jsp输出时的编码,不会作为header发出去的; 是告诉web Server jsp页面按照什么编码输出,即web服务器输出的响应流的编码。
(2). 第一阶段是jsp编译成.java,它会根据pageEncoding的设定读取jsp,结果是由指定的编码方案翻译成统一的UTF-8 JAVA源码(即.java)。
(3). 第二阶段是由JAVAC的JAVA源码至java byteCode的编译,不论JSP编写时候用的是什么编码方案,经过这个阶段的结果全部是UTF-8的encoding的java源码.JAVAC用UTF-8的encoding读取java源码,编译成UTF-8 encoding的二进制码(即.class),这是JVM对常数字串在二进制码(java encoding)内表达的规范。
(4). 第三阶段是Tomcat(或其的application container)载入和执行阶段二的来的JAVA二进制码,输出的结果,也就是在客户端见到的,这时隐藏在阶段一和阶段二的参数contentType就发挥了功效。
4. 和contentType效果一样的设置方式还有html页面charset, response.setCharacterEncoding(),response.setContentType(),response.setHeader(); response.setContentType(),response.setHeader(),优先级最好;
其次是response.setCharacterEncoding(); 再者是<%@page contentType=”text/html; chareset=gbk”%>;
最后是
http://boyadn.blog.163.com/blog/static/74230736201022655121696/
进程和线程的区别
进程是系统资源分配和调度的基本单位。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被CPU独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
http://blog.youkuaiyun.com/mxsgoden/article/details/8821936
同步、异步、阻塞和非阻塞的区别
synchronized修饰静态方法和普通方法时,这两个方法同步吗
class Test{
synchronized static void sayHello3(){
}
synchronized void getX(){
}
}
首先我们应该理解问这个题目的意思,题上问的是这两个方法是不是同步的,这两个方法一个是静态方法,一个是普通方法,但是他们都被synchronized关键字修饰,他们本身当然是同步的,但是题目意思仔细想想并不是这个意思,而是说这两个方法是否同步。 这两个方法都被synchronized修饰,这两个方法是否同步,问题在于他们所持有的锁是否相同,由于第一个方法时静态方法,他持有的锁应该是Test.class,而第二个方法时普通方法,他所持有的锁应该是Test类创建的实例对象,即this。由于这两个方法持有的锁是不同的,那这两个方法就不是同步的。
@ModelAttribute注解的工作原理
https://xiangwanpeng.github.io/2016/11/07/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3@ModelAttribute%E6%B3%A8%E8%A7%A3%E7%9A%84%E5%B7%A5%E4%BD%9C%E8%BF%87%E7%A8%8B/
http://www.voidcn.com/article/p-erjwxttk-bgd.html
线程中stop()和suspend()推荐使用的原因
stop()它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被”挂起”的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个 notify() 重新启动线程。
volatile变量的作用
锁提供了两种主要特性:互斥(mutual exclusion)和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的。如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。
Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end”)。
要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
对变量的写操作不依赖于当前值。
该变量没有包含在具有其他变量的不变式中。
https://www.ibm.com/developerworks/cn/java/j-jtp06197.html
sleep、wait、yield方法的区别
wait和sleep的主要区别是:
调用wait方法时,线程在等待的时候会释放掉它所获得的monitor,但是调用Thread调用wait方法时,线程在等待的时候会释放掉它所获得的monitor,但是调用Thread.sleep()方法时,线程在等待的时候仍然会持有monitor或者锁。另外,Java中的wait方法应在同步代码块中调用,但是sleep方法不需要。 另一个区别是Thread.sleep()方法是一个静态方法,作用在当前线程上;但是wait方法是一个实例方法,并且只能在其他线程调用本实例的notify()方法时被唤醒。另外,使用sleep方法时,被暂停的线程在被唤醒之后会立即进入就绪态(Runnable state),但是使用wait方法的时候,被暂停的线程会首先获得锁(译者注:阻塞态),然后再进入就绪态。所以,根据你的需求,如果你需要暂定你的线程一段特定的时间就使用sleep()方法,如果你想要实现线程间通信就使用wait()方法。
yield和sleep的主要是:
yield方法会临时暂停当前正在执行的线程,来让有同样优先级的正在等待的线程有机会执行。如果没有正在等待的线程,或者所有正在等待的线程的优先级都比较低,那么该线程会继续运行。执行了yield方法的线程什么时候会继续运行由线程调度器来决定,不同的厂商可能有不同的行为。yield方法不保证当前的线程会暂停或者停止,但是可以保证当前线程在调用yield方法时会放弃CPU。
http://www.jianshu.com/p/25e959037eed
线程中stop()不推荐使用的原因
http://blog.youkuaiyun.com/jiangwei0910410003/article/details/19900007
http://www.cnblogs.com/DreamDrive/p/5623804.html
Java线程的状态及切换
- 新建(new):新创建了一个线程对象。
- 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
- 运行(running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
- 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。 - 死亡(dead):线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
https://my.oschina.net/mingdongcheng/blog/139263
Java多线程中join方法的理解
thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。
例如:
public static void main(String[] args) throws Exception {
Runnable r = new JoinTest();
Thread t = new Thread(r);
t.start();
t.join(); //加入join()
System.out.println(a);
}
如果没有就加入t.join();,那么main方法当执行玩t.start()之后就是直接执行System.out.println(a);,因为t.start();只是代表新建一个线程执行相应的操作。
加入t.join();后,那么会等到t中run()方法执行完毕之后,才执行System.out.println(a);。
http://uule.iteye.com/blog/1101994
2017-10-08
org.springframework.web.servlet.DispatcherServlet 需要spring-mvc.jar
当需要用到javax.servlet.http.HttpServletRequest类时,不需要用maven来下载相应的jar包。直接项目右键->Properties->Java Build Path->Libraries->Add Library->Server Runtime,然后选择一个tomcat即可。
标签的 enctype 属性
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。
默认地,表单数据会编码为”application/x-www-form-urlencoded”。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 “+” 加号,特殊符号转换为 ASCII HEX 值)。
http://www.w3school.com.cn/tags/att_form_enctype.asp
XMLHttpRequest是什么
https://segmentfault.com/a/1190000004322487
http://www.w3school.com.cn/xmldom/dom_http.asp
框架介绍
EJB:
企业级JavaBean(Enterprise JavaBean, EJB)是一个用来构筑企业级应用的服务器端可被管理组件。Java企业版API(Java Enterprise Edition)中提供了对EJB的规范。 EJB是一个封装有某个应用程序之业务逻辑服务器端组件。
SSH:
SSH框架一般指的是Struts、Spring、Hibernate,后来Struts2代替了Struts。最近5年,Struts2已经被Spring MVC代替,而Hibernate基本也被iBatis/MyBatis代替。
J2SE、J2ME、J2EE:
J2SE就是Java2的标准版,主要用于桌面应用软件的编程;
J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;
J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
Hibernate:
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
===========================
spring的好处
在SSH框假中spring充当了管理容器的角色。我们都知道Hibernate用来做持久层,因为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不用书写大量的SQL语句。Struts是用来做应用层的,他它负责调用业务逻辑serivce层。所以SSH框架的流程大致是:Jsp页面—-Struts——Service(业务逻辑处理类)—Hibernate(左到右)。
以往单独使用Struts框架的时候,所有的业务方法类的生命周期,甚至是一些业务流程都是由Action来控制的。层与层之间耦合性太紧密了,既降低了数据访问的效率又使业务逻辑看起来很复杂,代码量也很多。
而spring框架中,从头到尾Action仅仅是充当了Service的控制工具,这些具体的业务方法是怎样实现的,他根本就不会管,也不会问,他只要知道这些业务实现类所提供的方法接口就可以了。
事务的处理:
spring:
在以往的JDBCTemplate中事务提交成功,异常处理都是通过Try/Catch来完成,而在Spring中。Spring容器集成了TransactionTemplate,她封装了所有对事务处理的功能,包括异常时事务回滚,操作成功时数据提交等复杂业务功能。这都是由Spring容器来管理,大大减少了程序员的代码量,也对事务有了很好的管理控制。
Hibernate
Hibernate中也有对事务的管理,hibernate中事务管理是通过SessionFactory创建和维护Session来完成。
http://blog.youkuaiyun.com/cynhafa/article/details/6205361
===========================
web.xml 配置中classpath: 与classpath*:的区别
首先 classpath是指 WEB-INF文件夹下的classes目录
解释classes含义:
1.存放各种资源配置文件 eg.init.properties log4j.properties struts.xml
2.存放模板文件 eg.actionerror.ftl
3.存放class文件 对应的是项目开发时的src目录编译文件
总结:这是一个定位资源的入口
classpath 和 classpath* 区别:
classpath:只会到你的class路径中查找找文件;
classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找.
http://perfy315.iteye.com/blog/2009258
==========================
Struts1和Struts2的区别
1. Struts2和Struts1.x的差别,最明显的就是Struts2是一个pull-MVC架构。这是什么意思呢?从开发者角度看,就是说需要显示给用户的数据可以直接从Action中获取,而不像Struts1.x那样,必须把相应的Bean存到Page、Request或者Session中才能获取。
2. Struts1.x必须继承org.apache.struts.action.Action或者其子类,表单数据封装在FormBean中。Struts2无须继承任何类型或实现任何接口,表单数据包含在Action中,通过Getter和Setter获取。
- Struts1.x要求Action类要扩展自一个抽象基类。Struts1.x的一个共有的问题是面向抽象类编程而不是面向接口编程。
- Struts1.x Action类是单例类,因为只有一个实例来控制所有的请求。Struts2 Action对象为每一个请求都实例化对象,所以没有线程安全的问题。
http://blog.youkuaiyun.com/bjyfb/article/details/8679523
=========================
servlet、filter、listener、interceptor的区别
http://blog.youkuaiyun.com/sundenskyqq/article/details/8549932
========================