java-散知识一

常用的创建数组的方式

1     int[] arr1 = new int[3];
2     arr1[0] = 1;
3     arr1[1] = 2;
4     arr1[2] = 3;
5     int[] arr2 = {1, 2, 3};
6     int[] arr3 = new int[]{1, 2, 3};

String的length()和数组的length

数组的length是其对象头中的一个字段,可以看成是数组的独特的属性,String内部持有一个char[],String的length()其实就是该char[]的length。

 

可变参数

jdk5引入了许多语法糖,其中就有可变参数,可变参数使得函数可以接收任意数量的参数,在调用函数方看来,这些参数是散列的,在持有可变参数的函数看来,这些参数就是一个数组。

1 private void fun(int a, int... b) {
2   System.out.println(b);//[I@61064425,[I表示整型数组类型
3 }

 

字段不可被覆盖

子类不会覆盖父类相同名字的字段,各个字段拥有独立的空间,静态类型决定引用谁的字段

 

外围类不能继承内部类

外围类不能继承普通内部类可以理解,因为普通内部类的实例化依赖于外围类的实例化,但外围类为什么不能继承静态内部类呢(静态内部类可以说是完全独立于外围类的,只是在类名上与外围类有关)?

外围类同样不能实现内部接口,但普通内部类可以实现内部接口。内部接口只能是static的(默认就是),访问级别没有限制(外围接口不能是static的,且访问级别不能是private)。

外围类继承、实现内部类、接口都会提示“循环继承“编译错误。

普通内部类可以用来实现类中重复使用的模块,这样的好处是可以方便的访问外围类的属性。内部类还可以弥补外围类单继承的不足,依托内部类继承需要的类来实现想要的功能。

泛型

java的泛型是假泛型,也是一种语法糖,其只在编译期可见,编译之后就被擦除了,运行时就是强制转换了(通过反射也可以获取到泛型信息)。

List<String>并不是List<Object>的子类,这是由于编译器会检查两个类的泛型,如果泛型不同则认为二者不具有父子级关系,在泛型相同的条件再检查类型的父子级关系,如ArrayList<String>是List<String>的子类。

 1 public static void main(String args[]) {
 2   ArrayList<String> al = new ArrayList<String>();
 3   al.add("abc");
 4   test(al);
 5 }
 6 
 7 public static void test(ArrayList<?> al){//这里如果是ArrayList<Object> al就会报错
 8   for(Object e: al){//不管是什么类型,其终究是Object的子类(泛型不能使基本类型)
 9     System.out.println(e);
10   }
11   //al.add(new Object());// 由于我们不知道?到底是什么类型,所以这里不能添加元素
12 }

List和List<?>

?是泛型中的通配符,代表任意,?与Object不同,Object就只能是Object,?表示我不知道它具体是什么。

List没有泛型约束,可以随意添加元素,随意性很大;

List<?>除了null外,不允许添加其他任何类型的元素;

extends和super

List< Object > - 可以包含Object及其子类的实例;

List< ? extends Number > - 可以包含Number及其子类的实例,但由于不知道下限是什么类型,所以只能以Number进行访问(访问上限),而不能添加除null之外的任何类型实例(添加下限);

List< ? super Number > -可以包含Number及其父类的实例,但由于不知道上限是什么,故只能将元素作为Object进行遍历(访问上限),且只能添加Number及其子类的实例(添加下限);

泛型与数组的比较

我们知道了List<String>和List<Object>并非父子关系,但String[]和Object[]确是父子关系,它们和泛型没有关系,数组本身就是java的一种引用类型。

jvm运行时会对数组存放的元素进行甄别

1 String[] strings = {"1", "2"};
2 Object[] objects = strings;
3 objects[0] = 1;//java.lang.ArrayStoreException: java.lang.Integer

异常体系

Error(通常是无法修正的致命性错误,比如StackOverflowError、OutOfMemoryError,当然也可以显示捕获)和RuntimeException(通常是可通过规范编码修复的异常,比如NullPointerException,当然也可以显示捕获)都属于不是必须捕获的Throwable,其余的Throwable都是必须捕获的(这些异常通常是无法人为控制的,但可通过捕获异常努力修复的)。

线程对象

最基本的创建线程的方式有两种:

实现Runnable接口的run方法,再将实现类传入Thread中;

继承Thread重写run方法来实现线程逻辑;

1 //Thread实现了Runnable,它的run方法
2 public void run() {
3     if (target != null) {
4         target.run();
5     }
6 }

高级一些的可以使用FutureTask,其本质也是一个Runnable,它的run方法如下

 1 public void run() {
 2   if (state != NEW ||
 3     !UNSAFE.compareAndSwapObject(this, runnerOffset,
 4                                  null, Thread.currentThread()))
 5     return;
 6   try {
 7     Callable<V> c = callable;
 8     if (c != null && state == NEW) {
 9       V result;
10       boolean ran;
11       try {
12         result = c.call();
13         ran = true;
14       } catch (Throwable ex) {
15         result = null;
16         ran = false;
17         setException(ex);
18       }
19       if (ran)
20         set(result);
21     }
22   } finally {
23     // runner must be non-null until state is settled to
24     // prevent concurrent calls to run()
25     runner = null;
26     // state must be re-read after nulling runner to prevent
27     // leaked interrupts
28     int s = state;
29     if (s >= INTERRUPTING)
30       handlePossibleCancellationInterrupt(s);
31   }
32 }
View Code

FileOutputStream和FileWriter

 Java API Specification:

FileOutputStream is meant for writing streams of raw bytes such as image data. 
For writing streams of characters, consider using FileWriter.

FileWriter可以看成是FileOutPutStream的装饰类,从起构造函数就可以看出

1     public FileWriter(String fileName) throws IOException {
2         super(new FileOutputStream(fileName));
3     }

将数组转换为List

Arrays.asList(1, 2, 3);

//Arrays.asList
public static <T> List<T> asList(T... a) {
  return new ArrayList<>(a);
}

我们知道java.util.ArrayList并没有一个可变参数的构造器,Arrays.asList使用的ArrayList其实是Arrays的一个内部静态类,该ArrayList不能进行增删操作(可以更新现有的元素),即它的元素数是一定的。

如果需要得到一个可变的List可以进行如下操作

new ArrayList<>(Arrays.asList(1, 2, 3));

 

finally、return、throw

如下函数最终会返回1,finally无论如何都会执行,执行至try中的return a++时,执行栈会将a++的结果0保存起来,然后执行finally,此时a的值为1,finally中遇到return就直接返回了,而不会再回到try中的return。如果finally中没有return,则会回到try中返回之前保存的值,即0。在这里,throw的返回效果和return一样。

 1 private int fun() {
 2   int a = 0;
 3   try{
 4     System.out.println("try");
 5     return a++;
 6   }finally {
 7     System.out.println("finally");
 8     return a;
 9   }
10 }

参考:https://www.programcreek.com/simple-java/

原文地址:https://www.cnblogs.com/holoyong/p/7509230.html