一些常见JAVA问题

原文:https://blog.csdn.net/weiyongxuan/article/details/45920765 

一、Java的异常的基类是java.lang.Throwable

二、守护线程

1、java中只有用户线程和守护线程

2、守护线程的典型是GC,垃圾回收器

3、守护线程是用来服务用户线程的

 

三、 volatile关键字
volatile关键字用在多线程同步中,可保证读取的可见性,JVM只是保证从主内存加载到线程工作内存的值是最新的读取值,而非cache中。但多个线程对

volatile的写操作,无法保证线程安全。例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的

值,在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6;线程2由于已经进行read,load操作,在进行运算之后,也

会更新主内存count的变量值为6;导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况

也就是说,volatile关键字,不能保证线程的安全

 

四、数值的边界
存在使i + 1 < i的数?答案:存在

如果i为int型,那么当i为int能表示的最大整数时,i+1就溢出变成负数了,此时不就<i了

存在使i > j || i <= j不成立的数?答案:存在

比如Double.NaN或Float.NaN

 

五、double和float

0.1234 默认是double类型的,如果是float类型的,要加上F或f

float a=1.23//是错的

 

六、字节流与字符流

以writer/reader为后缀的是字符流

以inputStream/outputstream为后缀的是字节流

 

七、接口

1、接口中的成员变量默认都是public、static、final类型的,必须被显示初始化。

2、接口中的方法默认都是public、abstract类型的。

3、接口中只能包含public、static、final类型的成员变量和public、abstract类型的成员方法。

4、接口没有构造方法,不能被实例化。

5、一个接口不能实现另一个接口,但它可以继承多个其他接口。

6、接口必须通过类来实现它的抽象方法。

7、与子类继承抽象父类相似,当类实现了某个接口时,它必须实现接口中所有的抽象方法,否则这个类必须被定义为抽象类。

 

八、java创建对象的方式
1) 用new语句创建对象,这是最常见的创建对象的方法。

(2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。

(3) 调用对象的clone()方法。

(4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

九、容器扩充
 ArrayList list = new ArrayList(20);中的list扩充几次()

默认ArrayList的长度是10个,所以如果你要往list里添加20个元素肯定要扩充一次(扩充为原来的1.5倍),但是这里显示指明了需要多少空间,所以就一次性为你分配这么多空间,也就是不需要扩充了

十、null
package com.weixuan.java.review;

/*
* 代码可以正常执行
* null值可以强制转换为任何java类类型,(String)null也是合法的。
* 但null强制转换后是无效对象,其返回值还是为null,而static方法的调用是和类名绑定的,
* 不借助对象进行访问所以能正确输出。反过来,没有static修饰就只能用对象进行访问,
* 使用null调用对象肯定会报空指针错
*/
public class NULL {

public static void fun() {
System.out.println("-----");
}

public static void main(String[] args) {

((NULL) null).fun();
}
}


十一、java代码的初始化顺序
(1)程序运行时第一件事就是试图访问TestCodeExecOrder .main方法(他是static的),这是加载器加载TestCodeExecOrder的编译代码,对他加载过程中如果发现他有一个父类TestCodeExecOrderHost,接着对父类进行加载;

(2)接着,父类中的static初始化被立刻进行,然后是子类的static初始化(此处的static包括:static变量和static代码块,谁在前,谁就先执行),此时必要的类加载完毕,就可以创建对象了

(3)此时,对对象中的普通成员变量初始化(有值得赋值,没值的赋默认值)(普通成员变量包括:普通成员变量和动态代码块,谁在前,谁就先执行),接着父类的构造方法被执行,然后是子类的构造方法
package com.weixuan.java.review;

class TestCodeExecOrderHost {
private int i = 9;
public int j;

private static int xx = print("static TestCodeExecOrderHost.xx init");
{
System.out.println(xx + "TestCodeExecOrderHost 动态代码块");
}
static {
System.out.println("TestCodeExecOrderHost static代码块");
}

public TestCodeExecOrderHost() {
System.out.println("TestCodeExecOrderHost i=" + i + " j=" + j);
j = 10;
}

public static int print(String s) {
System.out.println(s);
return 20;
}
}

public class TestCodeExecOrder extends TestCodeExecOrderHost {

static {
System.out.println("TestCodeExecOrder static代码块");
}// (3)静态代码块

// (1)和(2)的顺序决定了输出顺序,也就是说哪个在前,先走哪个代码
private int x = print("TestCodeExecOrderHost xx变量");// (2)普通成员变量
{
System.out.println(xx2 + "TestCodeExecOrderHost 动态代码块");
}// (1)动态代码块
// private int x = print("TestCodeExecOrderHost xx变量");//(2)普通成员变量

// (3)和(4)的顺序决定了输出顺序,也就是说哪个在前,先走哪个代码
private static int xx2 = print("static TestCodeExecOrder.xx2 init");// (4)static成员变量

public TestCodeExecOrder() {
System.out.println("TestCodeExecOrder j=" + j);
System.out.println("TestCodeExecOrder x=" + x);
}

public static void main(String[] args) {
System.out.println("TestCodeExecOrder main");
TestCodeExecOrder t = new TestCodeExecOrder();
}

/*
* static TestCodeExecOrderHost.xx init
* TestCodeExecOrderHost static代码块
* TestCodeExecOrder static代码块
* static TestCodeExecOrder.xx2 init
* TestCodeExecOrder main
* 20TestCodeExecOrderHost 动态代码块
* TestCodeExecOrderHost i=9 j=0
* TestCodeExecOrderHost xx变量
* 20TestCodeExecOrderHost 动态代码块
* TestCodeExecOrder j=10
* TestCodeExecOrder x=20
*/
}


十二、catch字句的执行顺序
当用多个catch语句时,从最前面的catch语句块依次先后进行异常类型匹配,如果父异常在子异常类之前,那么首先匹配的将是父异常类,子异常类将不会获得匹配的机会,也即子异常类型所在的catch语句块将是不可到达的语句。所以,一般将父类异常类即Exception老大放在catch语句块的最后一个

十三、关于初始化
Java中所有定义的基本类型或对象都必须初始化才能输出值,否则在编译时会报错

 

十四、抽象类和接口的比较
(1)接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的。

(2)abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是一个类却可以实现多个interface,实现多重继承。接口还有标识(里面          没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用。

(3)在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是 static final     的,不过在 interface中一般不定义数据成员),所有的成员方法默认都是 public abstract 类型的。

(4)abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is­a"关系,interface表示的是"has­a"关系。

(5)实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。抽象类中可以有非抽象方法。接口中则不能有实现方法。

(6)接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。抽象类中的变量默认是friendly 型,其值可以在子类中重新定义,也可以在子类中重新赋值。

十五、构造函数调用顺序

1、子类的构造过程中,必须调用其父类的构造方法    

2、如果子类的构造方法中既没有显式的调用基类构造方法,而基类中又没有无参的构造方法,则编译出错,所以,通常我们需要显示的:super(参数列表),来调用父类有参数的构造函数,此时无参的构造函数就不会被调用。

3、子类没有显式调用父类构造函数,不管子类构造函数是否带参数都默认调用父类无参的构造函数,若父类没有则编译出错

posted @ 2019-08-05 16:59  tuanz  阅读(400)  评论(0编辑  收藏  举报