1.运行结果
class
HelloA{
public
HelloA()
{
System.out.println(
"I’m A class "
);
}
static
{
System.out.println(
"static A"
);
}
}
public
class
HelloB extends HelloA{
public
HelloB()
{
System.out.println(
"I’m B class"
);
}
static
{
System.out.println(
"static B"
);
}
public
static
void
main (String[] args){
new
HelloB();
}
}
static A static B I’m A class I’m B class解析: 静态优先,父类优先,创建B对象,类加载器加载B检查有基类A,于是先加载A类,再加载B,静态代码块在类加载进来时执行一次,
结果staticA,staticB,之后调用B的构造函数,B类的构造函数里第一行隐藏的super(),调用A的构造器,结果:I’m A class I’m B class
2.
1
2
3
|
double
d1=-
0.5
;
System.out.println(
"Ceil d1="
+Math.ceil(d1));
System.out.println(
"floor d1="
+Math.floor(d1));
Ceil d1=-0.0 floor d1=-1.0
解析:
ceil 方法上有这么一段注释:If the argument value is less than zero but greater than -1.0, then the result is negative zero
如果参数小于0且大于-1.0,结果为 -0,这里符号不能省略。
天花板,向上取整数
ceil 和 floor 方法 上都有一句话:If the argument is NaN or an infinity or positive zero or negative zero, then the result is the same as the argument,
意思为:如果参数是 NaN、无穷、正 0、负 0,那么结果与参数相同,
如果是 -0.0,那么其结果是 -0.0
地板向下取整数
3.
Spring是一系列轻量级Java EE框架的集合 Spring中包含一个“依赖注入”模式的实现 使用Spring可以实现声明式事务 Spring提供了AOP方式的日志系统 错误,只提供了AOP,没有日志系统
4.
ArrayList list = new ArrayList(20);中的list扩充几次? 0
有点迷惑人,大家都知道默认ArrayList的长度是10个,所以如果你要往list里添加20个元素肯定要扩充一次(扩充为原来的1.5倍),
但是这里显示指明了需要多少空间,所以就一次性为你分配这么多空间,也就是不需要扩充了。
5.关于volatile关键字,下列描述不正确的是?
正确答案: B D 你的答案: D (错误)用volatile修饰的变量,每次更新对其他线程都是立即可见的。 对volatile变量的操作是原子性的。 对volatile变量的操作不会造成阻塞。 不依赖其他锁机制,多线程环境下的计数器可用volatile实现。
所谓
volatile的措施,就是
1. 每次从内存中取值,不从缓存中什么的拿值。这就保证了用
volatile修饰的共享变量,每次的更新对于其他线程都是可见的。
2.
volatile保证了其他线程的立即可见性,就没有保证原子性。
3.由于有些时候对
volatile的操作,不会被保存,说明不会造成阻塞。不可用与多线程环境下的计数器。
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与synchronized 块相比,volatile 变量所需的编码较少, 并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。 锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议, 这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程 是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。 Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全, 但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器、 互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end”)。 出于简易性或可伸缩性的考虑,您可能倾向于使用 volatile 变量而不是锁。当使用 volatile 变量而非锁时,某些习惯用法(idiom)更加易于编码和阅读。 此外,volatile 变量不会像锁那样造成线程阻塞,因此也很少造成可伸缩性问题。在某些情况下,如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。 您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
实际上,这些条件表明,可以被写入 volatile 变量的这些有效值独立于任何程序的状态,包括变量的当前状态。 第一个条件的限制使 volatile 变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作, 必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使x 的值在操作期间保持不变,而 volatile 变量无法实现这点。 (然而,如果将值调整为只从单个线程写入,那么可以忽略第一个条件。) 大多数编程情形都会与这两个条件的其中之一冲突,使得 volatile 变量不能像 synchronized 那样普遍适用于实现线程安全。 |