下列说法正确的是__B_。
A.Java程序经编译后会产生machine code(机器码)
B.Java程序经编译后会产生byte code (字节码)
C.Java程序经编译后会产生DLL(动态链接库)
D.以上都不正确
设 int x = 1 , int y = 2 , int z = 3,则表达式 y+=z–/++x 的值是___A__。
A.3
B.3.5
C.4
D.5
解:y = 2 + 3 / 2 = 3
0.6332的数据类型是__B___。
A.float
B.double
C.Float
D.Double
解:如果是float需要加f,即是0.6322f,默认的话就是double
Float和Double都是包装类
下列说法正确的有__C___。
A.class中的constructor不可省略
B.constructor必须与class同名,但方法不能与class同名
C.constructor在一个对象被new时执行
D.一个class只能定义一个constructor
以下关于继承的叙述正确的是__A___。
A.在Java中类只允许单一继承
B.在Java中一个类只能实现一个接口
C.在Java中一个类不能同时继承一个类和实现一个接口
D.在Java中接口只允许单一继承
解:D,类只允许单一继承,但接口支持多继承
解:A.子类拥有的成员数目可以等于父类拥有的成员数目
B.比如Animal类比dog类广
C.子类如果没有重写父类中的成员方法,就可以直接调用父类的方法
D.普通类单一继承
解:其他都是编译时异常
解:字符流:Reader和Writer
字节流:InputStream和OutputStream
class Super{
public float getNum(){return 3.0f;}
}
public class Sub extends Super{
}
A.public float getNum(){return 4.0f;}
B.public void getNum(){}
C.public void getNum(double d){}
D.public double getNum(float d){return 4.0d;}
解:A.方法重写
B.既不是方法重写,也不是方法重载。仅仅返回类型不同不足以称为方法的重载。
C、D.方法重载
在Java中,同一个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载(method overloading)。
参数列表又叫参数签名,包括参数的类型、参数的个数、参数的顺序,只要有一个不同就叫做参数列表不同。
说明:
参数列表不同包括:个数不同、顺序不同、类型不同。
仅仅参数变量名称不同是不可以的。
跟成员方法一样,构造方法也可以重载。
声明为final的方法不能被重载。
声明为static的方法不能被重载,但是能够被在此声明。
方法的重载的规则:
方法名称必须相同。
参数列表必须不同。
方法的返回类型可以相同也可以不相同。
仅仅返回类型不同不足以称为方法的重载。
public class Demo11 {
public static void add3(Integer i) {
int val = i.intValue();
val += 3;
i = new Integer(val);
}
public static void main(String args[]) {
Integer i = new Integer(0);
add3(i);
System.out.println(i.intValue());
}
}
what is the result?
A.compile fail
B.print out “0”
C.print out “3”
D.compile succeded but exception at line 3
下列场景中,__D___不会触发类加载过程。
A.创建类的实例
B.初始化子类
C.访问类的字面值常量(即类名.class)
D.访问对象的成员
下面代码的运行结果为:C_
public class Demo13{
public static void main (String[] args){
String s;
System.out.println("s=" + s);
}
}
A.代码得到编译,并输出“s=”
B.代码得到编译,并输出“s=null”
C.由于String s没有初始化,代码不能编译通过
D.代码得到编译,但捕获到NullPointException异常
解:局部变量使用的时候得初始化,不初始化你这引用变量指向谁呀你就打印输出呢。
成员变量你不赋值,系统会初始化。
所以代码如果这样写,打印的值为0.
public class Demo13{
public int i;
public static void main (String[] args){
//String s;
//System.out.println("s=" + s);
Demo13 demo13 = new Demo13();
System.out.println(demo13.i);
}
}
解:A.构造方法实例化用的,接口能实例化么?不能,那要构造方法干啥
抽象类有构造方法,因为抽象类有一些成员变量,子类可能会调用父类的构造方法实例化父类的成员变量。
B、C对
D.接口允许多继承
解:C.方法区是线程共享的
关于守护线程的说法,正确的是___A__。
A.所有非守护线程终止,即使存在守护线程,进程运行终止
B.所有守护线程终止,即使存在非守护线程,进程运行终止
C.只要有守护线程或者非守护进程其中之一存在,进程就不会终止
D.只要所有的守护线程和非守护线程终止运行之后,进程才会终止
下列方法被调用后,一定使调用线程改变当前状态的是__C___。
A.notify()
B.run()
C.sleep()
D.isAlive()
解:A.notify不放弃执行权也不放弃锁对象。
B.run()和线程调度没关系,run()是需要重写的
C.sleep使当前线程进入阻塞状态
D.isAlive判断是否活着
public class Demo18 {
public void m() {
Object o = new Float(3.14F);
Object[] oa = new Object[1];
oa[0] = o;
o = null;
oa[0] = null;
System.out.println(oa[0]);
}
}
对象o最早可以被垃圾回收器回收的位置是:
A.After line 4
B.After line 6
C.After line 7
D.After line 9(that is,as the method returns)
解:首先看一下动态数组的存储方式(week01_day05)。
可以看出,两个引用都不指向Float(3.14F)这个包装类对象的时候才会被回收。
JAVA语言对象状态的持久化是通过__C___实现的。
A.文件
B.管道
C.序列化
D.过滤器
在TCP/IP中,解决计算机到计算机之间通信问题的层次是__B___。
A.网络接口层
B.网际层
C.传输层
D.应用层
解:TCP/IP协议族分4个层次:
网络接口层(network interface layer):最底层,是负责网络层与硬件设备之间的联系。
网际层(Internet layer):解决的是计算机到计算机的通信问题。
传输层(transmission layer):解决的是计算机程序到计算机程序之间的通信问题。
应用层(application layer):提供一组常用的应用程序给用户
public class Demo21 {
public static final int END = Integer.MAX_VALUE;
public static final int START = END - 100;
public static void main(String[] args) {
int count = 0;
for (int i = START; i <= END; i++)
count++;
System.out.println(count);
}
}
答:这是个死循环,当i==Integer.MAX_VALUE这一次循环结束时,i自加1,这个时候栈溢出,i为-2147483648.(不理解的话看补码的加法那一节)
所以会先打印出从Integer.MAX_VALUE-100到Integer.MAX_VALUE
的这100个数,然后,从Integer.MIN_VALUE开始接着打印,直到Integer.MAX_VALUE,并重复
class Father {
int i = 10;
public Father() {
System.out.println(getI());
}
public int getI() {
return i;
}
}
class Son extends Father {
int i = 100;
public Son(int i) {
this.i = i;
}
@Override
public int getI() {
return i;
}
}
答:0
父类方法被子类覆盖,即使在父类中调用,调用到的也是子类方法,而此时父类对象还在初始化过程中,子类对象更是还未开始初始化,其成员变量的值还是默认值。
这段代码最好debug一下,一目了然
public class Demo23 {
public static void main(String[] args) {
final String pig = "length: 10";
final String dog = "length: " + pig.length();
System.out.println("Animals are equal: " + pig == dog);
}
}
答:false
因为先拼接"Animals are equal: " + pig得到新的字符串,然后在比较==
System.out.println("Animals are equal: " + (pig == dog));//当代码改成这样后
因为pig引用变量指向字符串常量池中的一个常量,值为"length: 10",
dog引用变量也指向堆中的一块内存,内存中保存的值也为"length: 10",
但是这两个内存地址不同,而 == 判断的是pig和dog指向的内存地址是否相同,不同,所以依然返回false
public class Demo24 {
public static void main(String[] args) {
String str1 = "hello";
String str2 = "he" + new String("llo");
System.err.println(str1 == str2);
}
}
答:false
str1引用变量指向字符串常量池中的一个常量,值为"hello",
str2引用变量指向内存中的一块内存空间
但是这两个内存地址不同,而 == 判断的是str1和str2指向的内存地址是否相同,不同,所以返回false
public class Demo25 {
public static void main(String args[]) {
Dog woofer = new Dog();
Dog nipper = new Basenji();
woofer.bark();
nipper.bark();
}
}
class Dog {
public static void bark() {
System.out.print("woof ");
}
}
class Basenji extends Dog {
public static void bark() {
}
}
答:woof woof
静态方法不能被覆盖,也不能构成多态。子类中的bark()并没有对父类中的bark()方法进行重写
第一个woof 是woofer.bark(); 执行父类的bark方法所打印出来的
第二个woof 是nipper.bark(); 既然静态方法不能被覆盖,也不能构成多态。所以父类引用执行父类的bark方法。
public class Demo26 {
public static void main(String[] args) {
System.out.println(decision());
}
static boolean decision() {
try {
return true;
} finally {
return false;
}
}
}
答:false
finally代码块中的内容实在try代码块的return语句中间执行的,而当finally中的代码块执行完后,已经不需要执行try代码块中return语句的后半部分了。
public class Demo27 {
public static void main(String[] args) {
int[] x = {0, 1, 2, 3};
for (int i = 0; i < 3; i += 2) {
try {
System.out.println(x[i + 2] / x[i] + x[i + 1]);
} catch (ArithmeticException e) {
System.out.println("errorl");
} catch (Exception e) {
System.out.println("error2");
}
}
}
}
答:
errorl
error2
循环总共执行两次
第一次:i = 0,输出:x[2]/x[0]+x[1],x[0]为0,除零异常
错误处理器中的代码,一旦执行完毕,紧接着程序继续正常执行,执行的是整个try代码块之后的代码
第二次:i = 2 , x[4]不存在,数组越界异常
public class Demo28 {
static {
System.out.println("C");
}
{
System.out.println("B");
}
public Demo28(){
System.out.println("A");
}
public static void main(String[] args) {
Demo28 testMain = new Demo28();
}
}
答:
C
B
A
静态代码块中的内容随着类加载而执行,最先执行
构造代码块中的内容随着对象的创建而执行,但其次序先于构造方法
构造代码块相当于把所有构造方法里面的公共部分提取出来了,执行构造方法时,先执行构造代码块里面的代码,再执行构造方法。
public class Demo29 extends Thread {
public static void main(String[] args) {
Demo29 bground = new Demo29();
bground.run();
}
public void start() {
for (int i = 0; i < 10; i++) {
System.out.println("B ground.start()" + i);
}
}
}
答:无打印结果
main方法中只有主线程一个线程在执行,
直接调用一个线程的run方法是不会启动一个子线程的,直接调用run方法相当于一个普通的方法调用
而且子类不对Thread类的run方法进行重写的话,啥也不执行,因为run()方法是一个抽象方法,也就是一个空方法。
public class Demo30 {
private Demo30 internalInstance = new Demo30();
public Demo30() throws Exception {
throw new Exception("I'm not coming out");
}
public static void main(String[] args) {
try {
Demo30 b = new Demo30();
System.out.println("Surprise!");
} catch (Exception ex)
{
System.out.println("I told you so");
}
}
}
答:Stackoverflow error 在创建对象,给成员变量赋值时,无限递归,( private Demo30 internalInstance = new Demo30();
)且没有递归出口
原始类型(基本数据类型),有8种,基本数据类型的变量一般创建在栈帧中
引用类型本质上是一个类,引用类型的对象一般创建在堆上
标准答案:
1.基本数据类型包括:byte,short,char, int,long,float,double,boolean
引用数据类型主要包括:类,接口等
基本数据类型的变量存储的是该类型变量的值,而引用数据类型的变量存储的是地址(比如堆中对象的地址)
wait, notify 和 notifyAll都在Object类中
wait方法会唤醒在其他线程中,在同一个锁对象上,调用了notify或notifyAll方法。而这些对象,不一定继承了Thread类,但一定继承了Object类,因为所有类都是Object的子类
标准答案:线程通信,其实是依靠锁对象,来完成的(对于wait方法而言,调用wait方法的对象,首先必须被当前线程,作为锁对象持有),而java语言中的锁对象,可以是任意对象,因此这些方法被定义在Object中
标准答案:方法重载是指在同一个类中定义同名方法,而这些方法名称相同,但方法签名不同。
方法重写,是指在子类中,修改父类中定义的方法的实现。因此,他们发生的范围是不同的,方法重载发生在一个任意类中,而方法重写,发生在子类中,而且发生方法重写和方法覆盖的条件也不相同(这里不再赘述),同时,方法重载是编译时多态,而方法重写是运行时多态的前提条件之一
在Java中,同一个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载(method overloading)。
参数列表又叫参数签名,包括参数的类型、参数的个数、参数的顺序,只要有一个不同就叫做参数列表不同。
说明:
参数列表不同包括:个数不同、顺序不同、类型不同。
仅仅参数变量名称不同是不可以的。
跟成员方法一样,构造方法也可以重载。
声明为final的方法不能被重载。
声明为static的方法不能被重载,但是能够被在此声明。
方法的重载的规则:
方法名称必须相同。
参数列表必须不同。
方法的返回类型可以相同也可以不相同。
仅仅返回类型不同不足以称为方法的重载。(因为只有返回值不同,参数列表都相同,调用的时候你知道调用的是哪个方法啊)
字节流中数据的逻辑单位是单个字节
字符流中数据的逻辑单位是单个字符对应的字节数据
所有的字符流都是包装流,都包装了一个字节流。其底层的数据传输都要基于字节流来完成。字符流本身只做了一件事情:编码和解码。
a)字符数据在内存中还是以二进制(字符的在编码表中对应的编码值)的形式保存和传输
b)而对于二进制的字节数据的写和读,字节流就已经能够很好的完成了
c) 但为了保证字符流中的数据是一个一个的完整字符,所以字符流在字节流的基础上,添加了编解码器,即在使用底层字节流写数据前,先利用编码器,对字符数据进行编码得到字符数据对应的二进制编码序列,然后利用底层字节流传输它们,同时,在读取数据的时候,先用解码器,将由底层字节流传输的字节数据,解码成一个一个的字符。
所以字符流的功能实现是字节流 + 编码表(基于编码表的编解码操作)
异步简单来说就是,线程之间,各自独立运行,互不影响,就好像线程之间“同时”,在各自做自己的事情,简单来说,就是我走你也走
同步和异步相对,同步是指线程之间不能在各自为政,自己运行自己的,而是在某些情况下等待其他线程。简单来说,就是我走你不走
线程天生就是异步执行的,而当多线程异步访问同一个共享数据的时候,为了保证共享数据访问的正确性,必须保证同时只有一个线程,能访问并修改共享变量的值,这意味着,如果一个线程正在,访问某共享变量,则其他所有要访问该共享变量的线程都需要等待,直到,该线程访问完毕。
== 对于基本数据类型的数据而言,比较的是内容,对于引用数据类型的数据而言,比较的引用变量,所指向的内存地址。
equals方法是Object类的方法,其默认实现是比较两个对象的内存地址是否相同,若想:要比较量对象的内容是否相同,则需要在子类中覆盖Object的equals方法
super.clone(),因为该方法其实是在调用Object的clone方法,首先实现对该对象自身的浅克隆,然后在针对,该对象的引用变量做进一步的处理
java中实现运行时多态的前提条件有哪些?
a. 继承
b. 要有方法覆盖
c. 父类引用指向子类对象
Java多线程中调用wait() 和 sleep()方法有什么不同?
Thread.sleep VS Object.wait()
相同点是两者都可以使一个线程处于阻塞状态
A. 所属不同:
a. sleep定义在Thread类,静态方法
b. wait定义在 Object类中,非静态方法
B. 唤醒条件不同
a. sleep: 休眠时间到
b. wait: 在其他线程中,在同一个锁对象上,调用了notify或notifyAll方法
C. 使用条件不同:
a. sleep 没有任何前提条件
b. wait(), 必须当前线程,持有锁对象,锁对象上调用wait()
D. 休眠时,对锁对象的持有,不同:(最最核心的区别)
a. 线程因为Sleep方法而处于阻塞状态的时候,在阻塞的时候不会放弃对锁的持有
b. 但是wait()方法,会在阻塞的时候,放弃锁对象持有
缓冲流可以从一定程度上改善Java程序的IO效率。因为,IO的底层实现,是要依靠操作系统内核的功能来实现的,而我们的java程序每次请求操作系统内核的功能完成IO的时候,都需要付出额外的代价。既然,每次完成IO操作,都需要付出一次通信代价,那么意味着,一次IO操作如果读写的数据越多,那么平均到每个字节(字符)的数据,所付出的额外代价就会越小。
而缓冲流,本身维护了一个较大的缓冲区,能够在和操作系统内核交互的过程中,一次读写较多的字节(字符)数据,从而在整个数据传输过程中,减少java程序和操作系统内核通信的次数。从而减少了,应用程序为了完成功能,所需要付出的额外代价
public class Demo41 {
public static void main(String[] args) {
String str = "what's up man?";
byte[] bytes = str.getBytes();
int i;
int hashcode = 0;
for (byte b : bytes) {
i = (int) b;
hashcode = (hashcode + i) % 27;
}
System.out.println("str的哈希码为:" + hashcode);
}
}
注:java不支持if(1)、while(0)这种写法,只能用if(true)或while(false)