Fork me on GitHub

Aoot examination

aoot examination

1. 接口和抽象类的区别

  • 接口是对动作的抽象(这个对象能做什么),抽象类是对根源的抽象(这个对象是什么)。
  • 两者都不能直接实例化,对接口实例化时,接口变量必须指向一个类对象(此类对象必须实现了所有的接口方法);对抽象类实例化时,抽象类变量必须指向一个子类对象(此子类对象必须实现了所有的抽象方法)。注:如果方法不能全部被类 A 实现,那么类 A 必然是抽象类。
  • 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
  • 抽象方法要被实现,所以不能是静态的,也不能是私有的。

2. 嵌套类,内部类的概念

  • 嵌套类:一个类的内部定义另一个类,就是嵌套类。分为静态(使用较少)和非静态两种。
  • 内部类:指非静态嵌套类。分为成员内部类、静态嵌套类、方法内部类、匿名内部类。

注:对于静态嵌套类,因为其中的所有成员和方法都默认是静态的,所以无法访问外部类中的非静态成员,由此静态嵌套类使用受限。

3. javadoc 标签哪些是类前面的,哪些是方法前面了?

  1. 类注释的标签有:author、version、
  2. 方法注释的标签有:param、return、throws、exception
  3. 通用:see 引用、since 描述文本(支持哪个 jdk 版本)、deprecated、link(链接文档用)

4. 防御性编程:

  • 目的:打造高质量的模块。
  • 设计系统的每个组件,让其尽可能的保护自己。
  • 预见在什么地方可能出现问题,然后创建一个环境来测试错误,当预见的问题出现的时候通知你,并执行一个你指定的损害控制动作

5. overload 和 override 深刻理解

  • override,重写。子类对父类的允许访问的方法的实现过程进行重新编写,外壳完全不变,核心重写。
    • 不能抛出比原方法更宽泛的异常。原来抛 IOException,重写后只能抛 IOException 或其子类。
    • final 方法不能被重写。
    • static 方法不能被重写,但可以被重新声明。
    • 构造方法不能被重写。
  • overload,重载。一个类中,方法名字相同,而参数不同,返回类型可同可不同。
    • 必须改变参数列表;
    • 访问修饰符可以改变;
    • 可以声明更广的检查异常;
    • 无法以返回值类型作为重载函数的区分标准。

6. Java 中哪些类型有兼容性,哪些类型没有兼容性?

java培训:基本数据类型之间的兼容性

“小”的数据类型可以直接赋给“大”的数据类型。
“大”的不能赋值给“小”的数据类型(会出现编译错误)

  • 整数类:long > int > short > byte
  • 浮点型:double > float
  • 整型数据类型可以赋给浮点数据类型
  • char 可以赋给 long 和 int ,但是不能赋给 short 和 byte (编译错误) 。
  • char 可以赋给float和double
  • 当整数型常量在 0~65535 之间时,可以被赋值给 char 型变量
  • char 型常量可以被赋值给整数类变量,只要整数变量的类型可以容纳 char 型文字常量所表示的数值。
  • 浮点型常量默认为 double 型,而 double 型常量不能赋值给 float 型变量。
  • boolean 与其他数据类型没有兼容性。

7. float 和 double 为什么不能用等号等号来比较。怎么比较?

JAVA - 判断两个浮点数相等

计算机表示浮点数( float 或 double 类型)都有一个精度限制,对于超出了精度限制的浮点数,计算机会把它们的精度之外的小数部分截断。因此,本来不相等的两个浮点数在计算机中可能就变成相等的了

  1. 设置误差精度
  2. 转换成字符串后使用 equals 方法比较,需要精度很高
  3. 转换成 Long 后使用==比较(即使用Double.doubleToLongBits()
  4. 使用 BigDecimal 类型的 equals 方法或 compareTo 方法

8. volatile 和 synchronize 的区别?

分别是什么:

  1. volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符。
  2. 一个声明为 volatile 类型的变量将在所有的线程中同步的获得数据,不论你在任何线程中更改了变量,其他的线程将立即得到同样的结果。所以 volatile 类型变量在性能上有所消耗。
    • 是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取(事实上并不确切)。
    • 很多Java程序员认为volatile是让CPU直接访问主存来避免visibility问题, 这是错误的观点。其实Java里面volatile就是放了一个full memory fence(理解:强制将L1、L2刷入线程间的缓存,即多线程可见)等待 write buffer flush 到缓存系统处理结束。参考分布式系统一致性的发展历史(一)中的解释。
  3. synchronized 获取和释放由监听器控制的锁,如果两个线程都使用一个监听器(即相同对象锁),那么监听器可以强制在一个时刻只有一个线程能处理代码块,这是最一般的同步。另外,synchronized 还能使内存同步。在实际当中,synchronized 使得所有的线程内存与主内存相同步。
    • 本质是:锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住
  4. volatile 只能在线程内存和主内存之间同步一个(或多个,限于写 volatile 变量之前所有对共享变量的值的改变)变量的值,而 synchronized 则同步在线程内存和主内存之间的所有变量的值,并且通过锁住和释放监听器来实现。

区别:

  1. volatile 是线程同步的轻量级实现,所以 volatile 的性能要比 synchronize 好;但 synchronize 的执行效率也不差;
  2. 多线程访问 volatile 不会发生阻塞;而 synchronize 会发生阻塞;
  3. volatile 能保证变量在私有内存和主内存间的同步,但不能保证变量的原子性;synchronize 可以保证变量原子性;
  4. volatile 是变量在多线程之间的可见性;synchronize 是多线程之间访问资源的同步性;
  5. volatile 标记的变量不会被编译器优化;synchronized 标记的变量可以被编译器优化。

 
对于 volatile 修饰的变量,可以解决变量读时可见性问题,无法保证原子性。对于多线程访问同一个实例变量还是需要加锁同步。

9. mvn/git/Junit 的命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
mvn compile
mvn test
mvn package
mvn clean
mvn install
mvn checkstyle:checkstyle
mvn test > test.log
mvn cobertura:cobertura
mvn javadoc


git init 将目标编程 git 仓库

// 新增文件到仓库
git add readme.txt
git commit -m "wrote a readme file"

git status 查看结果
git diff readme.txt 查看工作区与仓库中的区别

git log 查看日志记录

git reset --hard HEAD^ 强力回退

git push origin master 推送最新修改

git clone



10. maven 的目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
src - main - java
- resources
- filters
- webapp
- test - java
- resources
- filters
- it
- assembly
- site
LICENSE.txt
NOTICE.txt
README.txt

11. Java 的 IO 体系

推荐阅读:Java IO 体系

1

  1. 字节流
    InputStream、OutputStream:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    读取文本
    psvm(){
    FileInputStream fis = new FileInputStream("likehui.txt"); // try-catch Exception
    int n = fis.read();
    sysout((char)n); // print 文本中第一个字符,比如“H”
    fis.close();
    }

    // 复制图片
    psvm(){
    try {
    FileInputStream fis = new FileInputStream("src/main/resources/happy.png");
    FileOutputStream fos = new FileOutputStream("src/main/resources/happy3.png");
    int n = 0;
    byte[] b = new byte[1024];
    while((n = fis.read(b))!= -1){
    fos.write(b,0,n);
    }
    fis.close();
    fos.close();

    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
  2. 字符流

    1

    1
    略略略
  3. 序列化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // 其中 Goods 类实现了 Serializable接口
    psvm(){
    Goods gd001 = new Goods("gd001",0.2);
    try {
    FileOutputStream fos = new FileOutputStream("src/main/resources/imooc.txt");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    FileInputStream fis = new FileInputStream("src/main/resources/imooc.txt");
    ObjectInputStream ois = new ObjectInputStream(fis);
    oos.writeObject(gd001);
    oos.writeBoolean(true);
    oos.flush();

    Goods goods = (Goods) ois.readObject();
    System.out.println(goods);
    System.out.println(ois.readBoolean());
    fos.close();
    oos.close();
    fis.close();
    ois.close();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    }

12. decorate pattern

装饰模式动态的将责任附加到对象上,若要扩展功能,装饰模式提供了比继承更有弹性的替代方案

13. runtimeException 受检异常

必须捕获或抛出:checkedException
允许忽略:不可查的 RuntimeException(含子类)和 Error(含子类)

  1. 非检查异常,就是指编译器不要求强制处理的异常。一般指 RuntimeException 及其子类。
  2. 检查异常,就是编译器要求强制处理的异常。一般有:IO 异常、SQL 异常
  • RuntimeException 的子类:
    • NullPointerException;
    • ArrayIndexOutOfBoundsException;
    • ArithmeticException;
    • ClassCastException。

14. equals hashcode 怎么实现的

实现 equals 的方法:

  1. Use == to see if argument is a reference to this (optimization)
  2. Use instanceof to check if argument is of the correct type (properly handles null)
  3. Cast the argument to the correct type
  4. Check each “significant” field
  5. Check reflexivity, symmetry, transitivity
1
2
3
4
5
6
7
8
@Override
public boolean equals(Object obj){
if(this == obj) return true;
if(!(obj instanceof Person)) return false;
Person person = (Person)obj;
return this.name.equals(person.name):
}

实现 hashCode 的方法:

  1. 取一个非 0 的 int 作为初始值,比如 42,保存在 result 中。
  2. 计算你所关心的域(在 equals 起作用的)的 hashCode。如何生成属性的 hashCode 我们等一下再说,先假设生成的 hashCode 为 c。
  3. 组合所有的域,result = 31 * result + c。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class TestClass {
byte b;
char c;
short s;
int i;
long l;
float f;
double d;
String string;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

TestClass testClass = (TestClass) o;

if (b != testClass.b) return false;
if (c != testClass.c) return false;
if (s != testClass.s) return false;
if (i != testClass.i) return false;
if (l != testClass.l) return false;
if (Float.compare(testClass.f, f) != 0) return false;
if (Double.compare(testClass.d, d) != 0) return false;
return string != null ? string.equals(testClass.string) : testClass.string == null;

}

@Override
public int hashCode() {
int result;
long temp;
result = (int) b;
result = 31 * result + (int) c;
result = 31 * result + (int) s;
result = 31 * result + i;
result = 31 * result + (int) (l ^ (l >>> 32));
result = 31 * result + (f != +0.0f ? Float.floatToIntBits(f) : 0);
temp = Double.doubleToLongBits(d);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (string != null ? string.hashCode() : 0);
return result;
}
}
-------------The End-------------