8-1
解析:
解析:
永久代:长时间存在的对象
整个Java的垃圾回收是新生代和年老代的协作,这种叫做分代回收
Serial New收集器是针对新生代的收集器,采用的是复制算法
综上:新生代基本采用复制算法,老年代用标记整理算法,cms采用标记整理
解析:
this()才必须是构造函数中的第一个可执行语句,用this调用语句并不需要
String s = "hello";
String t = "hello";
char c[] = {'h', 'e', 'l', 'l', 'o'};
解析:
String s = "hello";
String t = "hello";
char c [ ] = {'h','e','1','1','o'};
System.out.println(s.equals (t)); //true s和t指向内存常量区的同一个字符串 ;
System.out.println(t.equals (c));//false 一个返回字符串,一个返回对象 ;
System.out.println(s==t);// true s和t指向内存常量区的同一个字符串 ;
System.out.println(t.equals (new String ("hello")));//true equal用于比较两个对象的值是否相同,和内存地址无关
8-2
解析:
常见的ASCII码值:空格为32;数字0为48;“A”为65;“a”为97
0-9:48-57
A-Z:65-90
a-z:97-122
解析:
sleep和wait的区别:
synchronized(x){
x.notify()
//或者wait()
}
4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。
D:线程暂停执行指定的时间而不是程序暂停执行指定的时间。
解析:
可以将this理解为对象,而类方法属于类,不属于对象,所以类方法前不能加this指针
A:类方法是指类中被static修饰的方法,无this指针
C:类方法是可以调用其他类的static方法的
D:可以在类方法中生成实例对象再调用实例方法。
解析:
A:‘a’是字符串,’ a’这个是空格和a,必须要用“ a”才可以
B:String有length()方法
C:int无法直接转成String类型
D:尾部添加字符串“100”
解析:
三种组合:
try…catch…finally
try…catch
try…finally
解析:
Java继承中对构造函数是不继承的,只是显示或者隐式调用
1.class Parent{
2.public float aFun(float a, float b) { }
3.}
4.class Child extends Parent{
5.
6.}
哪个插入到行5是不合法的?
解析:
方法重写应该遵循“三同一小一大”原则:
A是重写,但是默认访问修饰符比父类的小,插入第五行编译器会报错
B,D不是重写,因为形参列表和返回值类型不同,所以在第五行以普通方法对待,没有错误
C满足条件,是重写,正确。
public class SystemUtil{
public static boolean isAdmin(String userId){
return userId.toLowerCase()=="admin";
}
public static void main(String[] args){
System.out.println(isAdmin("Admin"));
}
}
解析:
在源码中toLowerCase
是重新new String()
解析:
Java语言中的异常处理包括声明异常,抛出异常,捕获异常,和处理异常四个环节。
throw用于抛出异常
throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异常对象。
try是用于检测被包住的语句块是否出现异常,如果有异常,则抛出异常,并执行catch语句
catch用于捕获从try中抛出的异常并做处理
finally语句块是不管有没有出现异常都要执行的内容
8-3
解析:
ABD选项的操作符都可用于float和double
只有%取余操作,只适合用于整型。
解析:
A:Java中的字符串存储在字符串常量区,不会改变,发生改变是会新创建一个对象
B:StringBuffer是线程安全的String Builder
C:StringBuilder跟StringBuffer功能相同,区别是StringBuilder不是线程安全
D:StringBuilder和StringBuffer底层都是以字符数组存放的,可以修改内容
解析:
泛型仅仅是Java的一颗语法糖,他不会影响Java虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码,顶多编译速度稍微慢一些,执行速度是完全没有什么区别的。
解析:
正解:0.5
x / y = (float) 1.0 / (float) 2.0 = 0.5;
解析:
内部类就不需要与文件名相同
解析:
B:在Java中,如果你输入一个小数,系统默认的是double类型的,这个式子相当于float f = double 11.1,明显错误。如果想要表达11.1为float类型,需要在11.1末尾加一个“f”标识你输入的是float类型即可。
public class Tester{
public static void main(String[] args){
Integer var1=new Integer(1);
Integer var2=var1;
doSomething(var2);
System.out.print(var1.intValue());
System.out.print(var1==var2);
}
public static void doSomething(Integer integer){
integer=new Integer(2);
}
}
解析:
Java中引用类型的实参向形参的传递,只是传递的引用,而不是传递的对象本身,如下:
一、运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常),IndexOutOfBoundsException(下标越界)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
二、非运行时异常(编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类,从语法角度讲必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException,SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
解析:
普通的类方法是可以和类名同名的,和构造方法唯一的区别就是,构造方法没有返回值。
public class foo {
public static void main(String sgf[]) {
StringBuffer a=new StringBuffer(“A”);
StringBuffer b=new StringBuffer(“B”);
operate(a,b);
System.out.println(a+”.”+b);
}
static void operate(StringBuffer x,StringBuffer y) {
x.append(y);
y=x;
}
}
往方法中传参,传的仅仅只是地址,而不是实际内存,所以不要以为y=x程序的执行,是b=a的执行。这两者是不相等的。
8-4
解析:
原生类是指Java中,数据类型分为基本数据(或叫做原生类,内置类型)和引用数据类型。
那么原生类为基本数据类型,有八种,这样转换的时候就有表达范围问题
解析:
A:JVM一旦启动,就会创建一个守护线程来检测是否需要有对象内存被释放
C:无法直接释放
D:不可以指定时间,System.gc(),只是提醒JVM可以进行一次Full GC,但是什么时候真正执行,还是不知道的。
public class Test{
private static int i=1;
public int getNext(){
return i++;
}
public static void main(String [] args){
Test test=new Test();
Test testObject=new Test();
test.getNext();
testObject.getNext();
System.out.println(testObject.getNext());
}
}
最后打印出的是什么?
解析:
return i++,先返回i,然后再i+1
注意:
副本与原数据是不相关的,不会相互影响。
不过一般方法传递时候,只有基本数据类型和String才会传递副本,其它的类型是按引用传递的。
Java只有值传递
解析:
年老代满,持久代满,System.gc()
8-5
解析:
URL(Uniform Resource Locator)统一资源定位符,能够对因特网的资源进行定位。
URL一般由四部分组成:<协议>://<主机>:<端口>/<路径>
现在最常用的<协议>为http协议
<主机>是指主机在因特网上的域名
hhtp协议的默认<端口>为80(可省略)
<路径>是指文件的路径
继承具有传递性,子类可以无条件向上转型
父类静态变量 -> 父类静态代码块
子类静态变量 -> 子类静态代码块
父类非静态变量 -> 父类非静态代码块
父类构造方法 -> 子类非静态变量
子类非静态代码块 -> 子类构造方法
解析:
一个文件的字符要写到一个文件中,首先需要读取这个文件,所以要先建立输入流,然后写到另一个文件,这时再建立输出流,所以要先建立输入流,在建立输出流。
int i=0;
Integer j = new Integer(0);
System.out.println(i==j);
System.out.println(j.equals(i));
解析:
class Two{ Byte x; } class PassO{ public static void main(String[] args){ PassO p=new PassO(); p.start(); } void start(){ Two t=new Two(); System.out.print(t.x+””); Two t2=fix(t); System.out.print(t.x+” ” +t2.x); } Two fix(Two tt){ tt.x=42; return tt; } }
解析:
基本类型和String=“”是传值,其他类型都是传引用。当然,也可以认为Java只有传值,因为一个是拷贝了栈中的值,一个是拷贝了引用的地址值。
public class Test {
public static void main(String [] args){
System.out.println(new B().getValue());
}
static class A{
protected int value;
public A(int v) {
setValue(v);
}
public void setValue(int value){
this.value = value;
}
public int getValue(){
try{
value++;
return value;
} catch(Exception e){
System.out.println(e.toString());
} finally {
this.setValue(value);
System.out.println(value);
}
return value;
}
}
static class B extends A{
public B() {
super(5);
setValue(getValue() - 3);
}
public void setValue(int value){
super.setValue(2 * value);
}
}
}
解析:
首先,super()函数指的是调用父类的构造方法
①
new B()
执行B的构造函数,第一行是super(5);
此时执行的是A的构造函数,A的构造函数调用的是setValue()方法,由于B重写了A的这个方法,
所以!!!执行的是B的 setValue()方法。
即传入的参数是2*5=10
此时,因为super,所以调用的是父类的 setValue()方法,即value=10
第一行执行完毕。
第二行是 setValue(getValue()-3);
B没有getValue()方法,故执行父类的此方法,
try返回的是value=10+1=11,保存在临时栈中
finally中调用this的方法,这个this指的是B的对象,又重写,故就是B的 setValue()方法
value=2*11=22,第一个打印到屏幕上的数字
接下来参数 getValue()-3=11-3=8
传入B的 setValue()方法
此时value=2*8=16
至此,new B()执行结束
②
new B(). getValue()
B没有 getValue(),故执行A的 getValue()
try返回16+1=17,保存到临时栈中
finally调用B的 setValue()方法
value=17*2=34,第二个打印到屏幕上面的数字
最后主函数打印返回值,也就是try保存到临时栈的17
class A {}
class B extends A {}
class C extends A {}
class D extends B {}
解析:
1. 只看尖括号里的!!!明确点和范围两个概念
2. 如果尖括号里的是一个类,那么尖括号里的就是一个点,比如List< A > ,List < B > ,List < Object >
3. 如果尖括号里面带有问号,那么代表一个范围,< ? extends A > 代表小于等于A的范围,< ? super A >代表大于等于A的范围,< ? > 代表全部范围。
4. 尖括号里的所有点之间的赋值都是错的,除非是两个相同的点
5. 尖括号小范围赋值给大范围,对!;大范围赋值给小范围,错!;如果某个点包含在某个范围里,那么可以赋值,否则,不能赋值!
6. List < ? >和List是相等的,都代表最大范围。
7. List既是点,也是范围,当表示范围时,表示最大范围。
8-6
String s1="abc"+"def";//1
String s2=new String(s1);//2
if(s1.equals(s2))//3
System.out.println(".equals succeeded");//4
if(s1==s2)//5
System.out.println("==succeeded");//6
解析:
1. 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。其中两种并发关系分别是同步和互斥。
2. 互斥:进程间相互排斥的使用临界资源的现象,就叫互斥
3. 同步:进程间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。进一步说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待。具有同步关系的一组并发进程相互发送的信息称为消息或事件。其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并发是指多核处理器的并发。
4. 并行:在单处理器中多道程序设计系统中,进程被交替执行,表现出一种并发的外部特征;在多处理器系统中,进程不仅可以交替执行,并且可以重叠执行。在多处理器上的程序才可以实现并行处理。从而可知,并行是针对多处理器而言的。并行是同时发生的多个并发事件,具有并发的含义,但并发不一定并行,也亦是说并发事件之间不一定要同一时刻发生
5. 多线程:多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码。多线程可以实现线程间的切换执行。
6. 异步:异步和同步是相对的,同步就是顺序执行,执行完一个再执行下一个,需要等待,协调运行。异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。线程就是实现异步的一个方式。异步是让调用方法的主线程不需要同步等待另一个线程的完成,从而可以让主线程干其它的事情。
异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。实现异步可以采用多线程技术或交给另外的进程来处理。
解析:
引用代表引用的是实际的对象,对引用的修改就是对对象的修改,可以理解为两把钥匙打开同一扇门。
值传递,传递的是原来值得副本。
引用传递,一般的引用类型在进行传递的时候,一开始形参和实参都是指向同一个地址的,这个时候形参对对象的改变会影响到实参。
传值传参的时候,我们在函数中改变了参数的值,其对应的变量的值并不改变,值类型传参就是将变量保存的内容复制到函数的形参中,他们两个是不同的变量,只不过保存的内容相同罢了
引用传参保存的是一个地址,这个地址里保存的是变量的具体值,而引用类型作为参数的时候,是将变量保存的地址值赋值到参数变量里,这样他们都指向了同一个内容,这样我们改变参数的成员的话,那么相应的变量的成员也会改变。
解析:
如果在子类中对父类继承来的成员变量进行重新定义,即出现了子类变量对父类变量的隐藏。
super代表父类对应的对象
public class StringDemo{
private static final String MESSAGE="taobao";
public static void main(String [] args) {
String a ="tao"+"bao";
String b="tao";
String c="bao";
System.out.println(a==MESSAGE);
System.out.println((b+c)==MESSAGE);
}
}
解析:
首先判断a==MESSAGE同一份字符串常量在内存中只有一份,因此是同一地址,返回true
再次比较(b+c)==MESSAGE这相当于new String(b+c)==MESSAGE这里new了一个String对象,所以返回false
8-7
解析:
静态方法中不能调用对象的变量,因为静态方法在类加载时就初始化,对象变量需要在新建对象之后才能使用
1.运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常),IndexOutOfException(下标越界异常),这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生
运行时异常的特点是Java编译器不会检查他,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获他,也没有throws子句声明抛出它,也会编译通过
2.非运行时异常(编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException,SQLiteException等以及用户自定义的Exception,一般情况下不自定义检查异常。
8-8
解析:
A:HashMap和HashTable两个类都实现了Map接口,二者保存K-V对
B:HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)
C:HashTable的方法是Synchronize的,而HashMap不是,在多个线程访问HashTable时,不需要自己为它的方法实现同步,而HashMap就必须提供外同步
解析:
A:ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 // 正确,这里的所谓动态数组并不是“有多少个元素就申请多少个空间”的意思,而是如果没指定数据大小,则申请默认大小为10的数据,当元素个数增加,数据无法存储时,系统会另申请一个长度为当前长度1.5倍的数组,然后把之前的数据拷贝到新建的数组
B:对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。 // 正确,ArrayList是数组,所以,直接定位到相应位置取元素,LinkedList是链表,所以需要从前往后遍历。
C:对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。// 正确 ,ArrayList的新增和删除就是数组的新增和删除,LinkList与链表一致。
D:ArrayList的空间浪费主要体现在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间。
// 正确,因为ArrayList空间的增长率为1.5倍,所以很可能留下一部分空间是没有用到的,因此,会造成浪费的情况。对于LinkedList的话,优于每个节点都需要额外的指针。
Java中true,false,null在Java中不是关键字,也不是保留字,它们只是显示常量值,但是你在程序中不能使用他们作为标识符。
byte b1=1,b2=2,b3,b6,b8;
final byte b4=4,b5=6,b7;
b3=(b1+b2); /*语句1*/
b6=b4+b5; /*语句2*/
b8=(b1+b4); /*语句3*/
b7=(b2+b5); /*语句4*/
System.out.println(b3+b6);
解析:
Java表达式转型规则,由低到高转换
1. 所有的byte,short,char型的值将被提升为int型
2. 如果有一个操作数是long型,计算结果是long型
3. 如果有一个操作数是float型,计算结果是float型
4. 如果有一个操作数是double型,计算结果是double型
5. 被final修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转换
语句1错误:b3=(b1+b2);自动转为int,所以正确写法为b3=(byte)(b1+b2);或者将b3定义为int;
语句2正确:b6=b4+b5;b4、b5为final类型,不会自动提升,所有和的类型视左边变量类型而定,即b6可以是任意数值类型;
语句3错误:b8=(b1+b4);虽然b4不会自动提升,但b1仍会自动提升,所以结果需要强转,b8=(byte)(b1+b4);
语句4错误:b7=(b2+b5); 同上。同时注意b7是final修饰,即只可赋值一次,便不可再改变。
8-9
解析:
比如A=B,只是把A对象的地址指向B对象的地址,所以其实对象只有一个,而不是产生了两个对象。
Hash家族分为几个小家族,分别是HashMap,Hashtable,TreeMap。
HashMap准许自己的键值对都可以为null。
Hashtable与TreeMap**允许了自己的键值对可以为”“**,但是不能触碰null的界限。
finally一定会在return之前执行,但是如果finally使用了return或者throw语句,将会使try-catch中的return或者throw失效。
即,finally中return会覆盖try-catch中的return语句
8-10
public class Demo{
int x=1;
int y;
public static void main(String [] args){
int z=2;
Demo t=new Demo();
System.out.println(t.x+t.y+z);
}
}
解析:
成员变量未初始化默认为0
局部变量参与运算前是必须要初始化的,比如下面的到吗就会编译出错,提示y必须要初始化!
public static void main(String[] args) {
int x = 1;
int y;
int z = x + y;
}
解析:
System是java.lang中的类,out为System中的一个静态成员变量,out是java.io.PrintStream类的对象,而println()是java.io.PrintStream类的方法,所以可以调用类.静态方法.println()方法
解析:
Java1.8,抽象类中的抽象方法和非抽象方法在不加修饰符的情况下,都是默认的default
关于抽象类
JDK 1.8以前,抽象类的方法默认访问权限为protected
JDK 1.8时,抽象类的方法默认访问权限变为default
关于接口
JDK 1.8以前,接口中的方法必须是public的
JDK 1.8时,接口中的方法可以是public的,也可以是default的
JDK 1.9时,接口中的方法可以是private的
解析:
构造函数不能被继承,构造方法只能被显示或隐式的调用
class Base{
public Base(String s){
System.out.print("B");
}
}
public class Derived extends Base{
public Derived (String s) {
System.out.print("D");
}
public static void main(String[] args){
new Derived("C");
}
}
解析:
子类构造方法再调用时必须先调用父类的,由于父类没有无参构造,必须再子类中显示调用,修改子类构造方法如下即可:
public Derived(String s){
super("s");
System.out.print("D");
}
8-11
解析:
A:Java的访问权限有public,protected,private,default,default不能修饰变量
C:普通变量不能使用abstract修饰,abstract一般修饰 方法和类
D:被定义为abstract的类需要被继承,而final不需要被继承,冲突
8-12
public class Test {
public static int a = 1;
public static void main(String[] args) {
int a = 10;
a++; Test.a++;
Test t=new Test();
System.out.println("a=" + a + " t.a=" + t.a);
}
}
解析:
Java采用局部优先的思想。局部变量可以和成员变量相同,使用标识符调用时,优先使用局部变量
8-13
一个文件中可以有多个public class,即外部类为public,还可以有public的内部类
一个文件中可以有多个类,可以是多个并列的类,也可以是外部类,内部类结合
一个类中,可以有多个main方法,这是重载,但是public static void main(String[] args)的方法只能有一个
类中,可以有main方法,也可以没有main方法,而有一个main()方法的时候,也可以是任意访问权限。因为这个类不一定要执行,可以只是辅助类
自动转换按从低到高的类型转换;强制类型转换必须在代码中声明,转换顺序不受限制
自动转换按从低到高的顺序转换
byte,short,char->int->long->float->double
8-14
解析:
JVM在判断两个class是否相等时,不仅要判断两个类名是否相等,而且要判断是否由同一个类加载器实例加载的
String s=”hello”;
String t=”hello”;
char c[] ={‘h’,’e’,’l’,’l’,’o’};
下列选项中返回false的语句是:
解析:
char c[]是一个数组,而且数组在堆上
解析:
hashcode和equals的约定关系如下:
1. 如果两个对象相等,那么它们一定有相同的哈希值(hashCode)
2. 如果两个对象的哈希值相等,那么这两个对象有可能相等也有可能不相等(需再通过equals来判断)
Boolean flag = false;
if (flag = true)
{
System.out.println(“true”);
}
else
{
System.out.println(“false”);
}
解析:
Java赋值运算是有返回值的,赋了什么值,就返回什么值。
Vector相当于一个线程安全的List
HashMap是非线程安全的,其对应的线程安全类是HashTable
Arraylist是非线程安全的,其对应的线程安全类是Vector
StringBuffer是线程安全的,相当于一个线程安全的StringBuilder
Properties实现了Map接口,是线程安全的
8-15
解析:
编译器将Java源代码编译成字节码class文件
类加载到JVM里面后,执行引擎把字节码转为可执行代码
执行的过程,再把可执行代码转为机器码,由底部的操作系统完成执行
boolean b=true?false:true==true?false:true;
System.out.println(b);
解析:
== 优先级高于三目运算
void waitForSignal()
{
Object obj = new Object();
synchronized(Thread.currentThread())
{
obj.wait();
obj.notify();
}
}
解析:
两个错误:
1. wait()方法要以try/catch包裹,或是掷出InterruptedException才行
2. synchronized的目标与wait()方法的物件不相同,会有IllegalMonitorStateException,不过InterruptedException会先出现。
8-16
String x="fmn";
x.toUpperCase();
String y=x.replace('f','F');
y=y+"wxy";
System.out.println(y);
解析:
String x = “fmn”;”fmn”是在常量池里的不可变对象
x.toUpperCase();在堆中new一个”FMN”对象,但无任何引用指向它
String y = x.replace(“f”,”F”);在堆中new一个“FMN”对象,y指向它
y=y+”wxy”;在堆中重新new一个“Fmnwxy”对象,修改y指向,现在y指向它
public class Test
{
public int x;
public static void main(String []args)
{
System. out. println("Value is" + x);
}
}
解析:
非静态成员变量只能被类的实例化对象引用,因此这里在静态方法中访问x会造成编译错误
class A {
private String a = “aa”;
public boolean methodB() {
String b = “bb”;
final String c = “cc”;
}
}
解析:
a是类中的成员变量,存放在堆区
b,c都是方法中的局部变量,存放在栈区
为什么不是方法区?因为题目问的是变量存放位置,而不是变量指向内容的存放位置。
堆区:只存放类对象,线程共享
方法区:又叫静态存储区,存放class文件和静态数据,线程共享
栈区:存放方法局部变量,基本类型变量区,执行环境上下文,操作执行区,线程不共享。
8-17
解析:
Java中类是单继承,但接口可以多继承。
Interfere1 extends Interface2,Interface3…
解析:
如果父类中的某个方法使用了synchronized关键字,而子类中也覆盖了这个方法,默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上synchronized关键字才可。当然,也可以在子类中调用父类中相应的方法,这样虽然子类中的方法并不是同步的,但子类调用了父类中的同步方法,也就相当子类也同步
低级向高级是隐式类型转换
高级向低级必须强制类型转换,
byte
解析:
A:Vector相当于一个线程安全的List
B:HashMap是非线程安全的,其对应的线程安全类HashTable
C:ArrayList是非线程安全的,其对应的线程安全类是Vector
D:StringBuffer是线程安全的,相当于一个线程安全的StringBuffer
E:Properties实现Map接口,是线程安全
8-18
解析:
Java中,标识符,指用于给变量,类,方法等命名的名称。
1. 标识以数字,字符,下划线及$美元符号,组成(不包括@,%,空格等),不能以数字开头
2. 不能与Java关键字重复
3. 严格区分大小写
解析:
1. 如果是本类使用,可以直接就用静态变量名
2. 如果是其它类使用,可以使用类名来调用,也可以创建一个实例对象来调用
3. 如果静态变量所在的类是静态类,那么不管在本类里或在其他外部类,都可以直接使用静态变量名。
解析:
内部类可以是静态static的,也可以用public,default,protected和private修饰
外部类的修饰符只能是public,abstract,final
8-19
解析:
A:一个类有多个构造方法比那是重载的表现。重载参数列表不同,A正确
B:构造方法是再对象创建时就被调用,用于初始化
C:构造方法是给与之对应的对象进行初始化,初始化的动作只执行一次
D:构造方法必须与所在类的名称同名
解析:
第一个在堆中
第二个在字符串常量池中
如果在Java字符串常量池中已经存在,就只会创建一个
解析:
用new创建的对象在堆区
函数中的临时变量在栈区
Java中的字符串在字符串常量区
栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中
堆:存放用New产生的数据
静态域:存放在对象中用static定义的静态成员
常量池:存放常量
解析:
abstract类的子类可以实现超类所有的抽象方法,也可以实现超类的部分抽象方法
如果超类还有抽象方法未被子类实现,那么该子类也是abstract
8-20
1.
2.public class Interesting{
3. // 省略代码
4.}
解析:
一个.java文件中,可以有多个类,包括内部类和外部类。考虑到内部类的原因,一个.java文件中可以有多个public类但是对于外部类而言,一个.java文件必须只能有一个public类,同时这个类的类名必须和.java文件名一致(包括大小写)
解析:
A:HashMap实现了Map接口,它的key和value都可以是null,但是Hashtable中,key和value都不能是null
B:ArrayList与LinkedList都实现了List接口,继承了AbstractList类
C:ArrayList底层是动态数组的实现,随机位置添加和删除,都需要移动数组的数据,而LinkedList底层是双向链表,只需要修改Node节点的引用
D:随机访问数组比链表快
解析:
JDK以后,抽象类或者抽象方法改为默认dedault
解析:
A,Vector相当于一个线程安全的List
B,HashMap是非线程安全的,其对应的线程安全类是HashTable
C,Arraylist是非线程安全的,其对应的线程安全类是Vector
D,StringBuffer是线程安全的,相当于一个线程安全的StringBuilder
E,Properties继承了Hashtable,是线程安全的
8-21
public class Cat
{
long length;
public Cat(long l)
{
length = 1;
}
public static void main(String arg[])
{
Cat c1, c2, c3;
c1 = new Cat(10L);
c2 = new Cat(10L);
c3 = c2;
long m = 21L;
}
}
解析:
A ,c1和c2是两个参数相同的不同对象,c1!=c2,返回false
B ,c2和c3指向同一个引用,所以c2==c3,返回true
C, m与c1是不同类型,不相等,返回false
D,c1没有定义equals方法,默认调用Object类的equals方法,返回false
new关键字生成的对象存在堆内存中,c1和c2指向的是不同的对象,==判断两个变量是否相等,若为基本类型,且都是数值类型返回true,引用类型则必须指向同一个对象才会返回true,故c1和从c2不相等;
c2直接赋值给c3,二者指向的是同一个堆内对象,故二者相等
m为基本类型,c1为对象,二者不相等;
public class ZeroTest {
public static void main(String[] args) {
try{
int i = 100 / 0;
System.out.print(i);
}catch(Exception e){
System.out.print(1);
throw new RuntimeException();
}finally{
System.out.print(2);
}
System.out.print(3);
}
}
解析:
try catch 是直接处理,处理完成之后程序继续往下执行,throw则是将异常抛给它的上一级处理,程序便不往下执行了,throw则是将异常抛给它的上一级处理,程序便不往下执行了。
本题的catch 语句块里面,打印完1之后,又抛出一个RuntimeException,程序并没有处理他,而是直接抛出,因此执行完finally语句块之后,程序终止了
Integer i01 = 59;
int i02 = 59;
Integer i03 =Integer.valueOf(59);
Integer i04 = new Integer(59);
解析:
Integer的valueOf方法
这个方法就是返回一个Integer对象,只是在返回之前,看作了一个判断,判断当前i的值是否在[-128,127]区间,且IntegerCache中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新的对象。
这里,程序初次运行,没有59,所以直接创建一个新对象
public class Demo {
class Super{
int flag=1;
Super(){test();}
void test(){
System.out.println("Super.test() flag="+flag);
}
}
class Sub extends Super{
Sub(int i){
flag=i;
System.out.println("Sub.Sub()flag="+flag);
}
void test(){
System.out.println("Sub.test()flag="+flag);
}
}
public static void main(String[] args) {
new Demo().new Sub(5);
}
}
解析:
在继承中代码的执行顺序为:
1. 父类静态对象,父类静态代码块
2. 子类静态对象,子类静态代码块
3. 父类非静态对象,父类非静态代码块
4. 父类构造函数
5. 子类非静态对象,子类非静态代码块
6. 子类构造函数
8-24
解析:
A:类的实例方法是与该类的实例对象相关联的,不能直接调用,只能通过创建超类的一个实例对象,再进行调用
B:当父类的类方法定义为private时,对子类是不可见的,所以子类无法调用。
C:子类具体的实例方法对父类是不可见的,所以无法直接调用,只能通过创建子类的一个实例对象,再进行调用
D:实例方法可以调用自己类中的实例方法。
8-25
解析:
只是在栈中两个变量的符号引用指向了同一个对象的地址,不是产生了两个对象。
解析:
Socket套接字
就是源Ip地址,目标Ip地址,源端口号和目标端口号的组合
int i=0;
int j=0;
if((++i>0)||(++j>0))
{ //打印出i和j的值。 }
解析:
&&和||为短路与,短路或
&&若前面的表达式为false,整个逻辑表达式为false,所以后面的表达式无论true和false都无法影响整个表达式的逻辑结果,所以为了提高代码执行速率,后面的表达式就不会执行。
同理,若前面为true,则后面的表达式无需计算
&和|为不短路与,不短路或
无论什么情况,前面的和后面的都要执行
解析:
public class Father {
public void say(){
System.out.println("father");
}
public static void action(){
System.out.println("爸爸打儿子!");
}
}
public class Son extends Father{
public void say() {
System.out.println("son");
}
public static void action(){
System.out.println("打打!");
}
public static void main(String[] args) {
Father f=new Son();
f.say();
f.action();
}
}
输出:son
爸爸打儿子!
当调用say方法执行的是Son的方法,也就是重写say方法
而当调用action方法时,执行的是father的方法
普通方法:运用的是动态单分配,是根据new的类型确定对象,从而确定调用的方法
静态方法:运用的是静态多分配,即根据静态类型确定对象,因此不是根据new的类型确定调用的方法。
解析:
构造函数不能被继承,构造方法只能被显示或隐式的调用
public class f{
public static void main(String[] args){
String foo1 = args[1];
String foo2 = args[2];
String foo3 = args[3];
}
}
命令是:java T11 a b c
解析:
运行Java命令,没有T11对应的类,会报找不到或者无法加载主类。
8-26
B继承A,new B会:
1. 把A的静态的执行完,执行B的静态的
2. 再执行A的初始化代码块,构造函数
3. 再执行B的初始化代码块,构造函数
解析:
除去Java中关键字,Java中标识符是:字下美人数
字母——下划线——美元符号——人民币——数字
数字不能放首位
public class Test {
public int aMethod(){
static int i = 0;
i++;
return i;
}
public static void main(String args[]){
Test test = new Test();
test.aMethod();
int j = test.aMethod();
System.out.println(j);
}
}
解析:
静态变量只能在类主体中定义,不能在方法中定义。
静态变量属于类所有而不属于方法
解析:
hashMap在单线程中使用大大提高效率,在多线程的情况下使用hashTable来确保安全。
hashTable中使用synchronized关键字来实现安全机制,但是synchronized是对整张hash表进行锁定即让线程独享整张hash表,在安全同时造成了浪费。
concurrentHashMap采用分段加锁的机制来确保安全。
Arrays.asList():将一个数组转化为一个List对象,这个方法会返回一个ArrayList类型的对象,这个ArrayList类并非java.util.ArrayList类,而是Arrays类的静态内部类。用这个对象对列表进行CRUD操作,会报UnsupportedOperationException异常。
解析:
1. 类只能用public,abstract,final修饰
2. 内部类和成员变量一样可以用所有访问权限修饰符修饰
3. 局部内部类和局部变量一样不能用访问权限修饰符
Boolean flag = false;
if (flag = true)
{
System.out.println(“true”);
}
else
{
System.out.println(“false”);
}
解析:
Boolean修饰的变量为包装类型,初始化值为false,进行赋值时会调用Boolean.valueOf(boolean b)方法自动拆箱为基本数据类型,因此赋值后flag值为true,输出文本true。如果使用==比较,则输出文本false。if的语句比较,除boolean外的其他类型都不能使用赋值语句,否则会提示无法转成布尔值。
解析:
volatile与synchronized的区别:
volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
volatile仅能实现变量的修改可见性,但不具备原子特性,而synchronized则可以保证变量的修改可见性和原子性.
volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.
volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化.
8-27
解析:
floor:意味地板,指向下取整,返回不大于它的最大整数
cell:意味天花板,指向上取整,返回不小于它的最小整数
round:意味大约,+0.5然后floor。即当前值+0.5向下取整。
参考
(1)负数
Math.round(-11.6) = -12
Math.round(-11.5) = -11
(2)正数
Math.round(11.5) = 12
Math.round(11.6) = 12
解析:
wait方法会导致对象放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
注意:是准备获取对象锁进入运行状态,而不是立即获得
也就是说,wait进入等待锁定池,只有针对此对象发出notify方法获得对象锁进入“就绪”状态。是就绪状态而不是运行状态
public class Square {
long width;
public Square(long l) {
width = l;
}
public static void main(String arg[]) {
Square a, b, c;
a = new Square(42L);
b = new Square(42L);
c = b;
long s = 42L;
}
}
D:程序会把s封装成一个Long类型,由于Square没有重写Object的equals方法,所以调用的是Object类的equals方法,源码如下:
public boolean equals(Object obj) {
return (this == obj);
}
其实就是判断两个引用是否相等,所以D错。
解析:
System是java.lang中的类,out是System中的一个静态成员,out是java.io.PrintStream类的对象,而println()是java.io.PrintStream类的方法。
class Foo {
final int i;
int j;
public void doSomething() {
System.out.println(++j + i);
}
}
解析:
final作为成员对象存在时,必须初始化;但是,如果不初始化,也可以在类的构造函数中初始化。
因为Java允许将数据成员声明为final,却不赋值。但是,blank final必须在使用前初始化,且必须在构造函数中初始化。
父类没有无参构造函数,所以子类需要在自己的构造函数中显示调用父类的构造函数。否则报错。
堆区:只存放类对象,线程共享
方法区:又叫静态存储区,存放class文件和静态数据,线程共享
栈区:存放局部变量,基本类型变量区,执行上下文,操作指令区,线程不共享。
解析:
全部正确
普通的Java对象是通过new关键字把对应类的字节码文件加载到内存,然后创建该对象的。
反射是通过一个名为Class的特殊类,用Class.forName(“className”);得到类的字节码对象,然后用newInstance()方法在虚拟机内部构造这个对象(针对无参构造函数)
也就是说,反射机制让我们可以先拿到Java类对应的字节码对象,然后动态的进行任何可能的操作。
使用反射的主要作用是方便程序的扩展。
Java中true,false,null在Java中不是关键字,也不是保留字,它们只是显式常量值,但是你在程序中不能使用它们作为标识符。
8-28
解析:
A:CopyOnWriteArrayList适用于写少读多的并发场景
B:ReadWriteLock即为读写锁,他要求写与写之间互斥,读与写之间互斥,读与读之间可以并发执行。在读多写少的情况下可以提高效率
C:ConcurrentHashMap是同步的HashMap,读写都加锁
D:volatile只保证多线程操作的可见性,不保证原子性
解析:
简单说,字符流是字节流根据字节流所要求的编码集解析获得的
也就是:字符流=字节流+编码集
所以和字符流有关的类都有操作编码集(Unicode)的能力
后缀是Stream的都是字节流,其他的都是字符流
解析:
A:抽象方法只可以被public,protected修饰
B:final可以修饰类,方法,变量,分别表示:类不可被继承,方法不能重写,该变量是常量
C:static final可以表达在一起来修饰方法,表示的是该方法是静态的不可重写的方法
D:private修饰方法(很常见)表示私有方法,本类可以访问,外界不能访问
8-30
标识符:
字母,数字,下划线,$,数字
开头不能是数字不能是关键字
class C {
C() {
System.out.print("C");
}
}
class A {
C c = new C();
A() {
this("A");
System.out.print("A");
}
A(String s) {
System.out.print(s);
}
}
class Test extends A {
Test() {
super("B");
System.out.print("B");
}
public static void main(String[] args) {
new Test();
}
}
解析:
初始化过程是这样的:
1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
3.其次,初始化父类的普通成员变量和代码块,在执行父类的构造方法;
4.最后,初始化子类的普通成员变量和代码块,在执行子类的构造方法;
(1)初始化父类的普通成员变量和代码块,执行 C c = new C(); 输出C
(2)super(“B”); 表示调用父类的构造方法,不调用父类的无参构造函数,输出B
(3) System.out.print(“B”);
所以输出CBB
注意:
1.是先执行父类的构造函数再执行子类的构造函数,这个执行顺序是没有错的。但是还有一个逻辑顺序,为什么平白无故的执行父类的构造函数呢?因为子类调用了(或默认调用了)父类的构造函数,在逻辑上是子类先执行
2.因为已经显式调用父类带参构造函数super(“B”)了,所以子类调用的父类构造器是A(String s),而不是无参构造器,除非在子类构造器里没有显式调用父类构造器,编译器才在子类构造器为其默认添加super();
finally中return语句会覆盖try-catch中的return语句
解析
由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器。
1. 使用匿名内部类时,必须继承一个类或实现一个接口
2. 匿名内部类由于没有名字,因此不能定义构造函数
3. 匿名内部类中不能含有静态成员变量和静态方法
解析:
总结来说为:
方法名相同,参数类型相同
子类返回类型等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限。
详细的说明为:
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。 即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常IOException,但是在重写这个方法的时候不能抛出Exception异常,因为Exception是IOException的父类,只能抛出IOException的子类异常。
8-31
解析:
1. 如果是本类使用,可以直接就用静态变量名
2. 如果是其它类使用,可以使用类名来调用,也可以创建一个实例对象来调用
3. 如果静态变量所在的类是静态类,那么不管在本类或其它外部类,都可以直接使用静态变量名
解析:
A:在final定义的方法里,不是必须要用final定义变量
B:final定义的变量不是必须要在定义的同时完成初始化,也可以在构造方法中完成初始化
C:final修饰方法,不能被子类重写,但是可以重载
D:final定义变量,可以用static也可以不用
解析:
会产生信息丢失不如说丢失精度,而精度丢失只会发生在从大范围到小范围的转换。
byte 1字节
char 2字节
short 2字节
int 4字节
float 4字节
long 8字节
double 8字节
boolean 1字节
int i=0;
int j=0;
if((++i>0)||(++j>0))
{ //打印出i和j的值。 }
解析:
&& || 短路与 和 短路或,所谓的短路就是前部分能确定结果就不执行后面部分
解析:
this()才必须是构造函数中的第一个可执行语句,this调用语句并不需要
this()和super()为构造方法,作用是在JVM堆中构建一个对象。因此避免多次创建对象,同一方法内只能调用一次this()或super()。同时为了避免操作对象时对象还没构建成功,需要this()和super()的调用在第一行实现(以此来创建对象)
解析:
A:vector是线程安全的ArrayList,在内存中占用连续的空间。初始时有一个初始大小,当数据条数大于这个初始大小后会重写分配一个更大的连续空间。如果Vector定义为保存Object则可以存放任意类型
B:try{}catch{}会增加额外的开销
C:接口中不能有变量,其中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统一的属性。
D:子类可以访问父类受保护的成员
解析:
注意jvm的版本,好比人穿裤子,一条裤子能被任何人穿上吗