Java基础中的一些问题和坑

这篇文章列举Java基础中的一些容易被忽略的问题,这篇文章将会不断更新,只要想到或者遇到问题,就会记录在这里,供大家分享。
&&和||是短路判断,左边可以判断最终结果,右边就不再执行,&和|不是短路判断,左右两边都会被判断

int a = 3;
int b = (a++)+(++a)*2+5;结果为5+8+5=18

int x = 3;
boolean b = (x++)>3;
b为false

负数奇数的余数是-1,所以判断偶数要用a%2==0,而不能用a%2<1等等

do{}while();后面有个分号

字符类型和字符类型数组的默认值为/u0000

类的成员变量有默认值,方法的局部变量没有默认值

scanner的string是字符流,int是字节流,混在一起使用就会出现Bug,建议全部使用nextLine

泛型只能是引用类型,int要用Integer

equals比较的时候,常量要写在前面,因为变量有可能为null,null调用equals会报空指针异常

字符串的subString方法含头不含尾,结尾要多一位才能正确截取

substring(0)返回字符串本身

字符串的split方法切分英文句点.的时候必须用”\.”

Arrays.sort()方法默认按照升序从小到大排序,字符串按照字母顺序

调用成员变量和方法的时候,优先调用子类的,子类没有就找父类的

子类重写方法返回值的范围可以小于等于父类,父类方法返回Object,子类可以返回String
子类重写方法的权限修饰符必须大于等于符类,父类protected,子类可以是public

只有子类的构造方法才能调用父类的构造方法
而且一个子类构造方法中不能调用两次父类构造方法
父类构造方法必须在子类构造方法的第一行

本类构造方法调用本类其他构造方法也只能调用一次,也必须在第一行
super和this不能在同一个构造方法中使用
this不能循环调用

重写方法必须方法名参数列表返回值都一样

java8的接口有默认方法default和静态方法,默认方法可以选择重写也可以不重写
java9的接口可以包含私有方法

接口没有构造方法,没有静态代码块

一个类继承的两个接口里有同名默认方法,那么这个类必须覆盖重写

父类和接口方法冲突,优先用父类的

向上造型以后,子类的成员变量不能被调用,父子类同名的成员变量是父类的
向上造型以后,子类有的方法,优先用子类,子类没有找父类

内部类编译后的.class文件格式为:外部类 . c l a s s 符号

内部类是给外部类的成员方法使用的
外.内 名 = new 外().new 内();

访问变量

public class Outer{
    int num = 10;
    public class Inner{
        int num = 20;
        public void method(){
            int num = 30;
            System.out.println(num);//30
            System.out.println(this.num);//20
            System.out.println(Outer.this.num);//10
        }
    }
    public static void main(String[] args) {
        new T().new S().ss();
    }
}

局部内部类访问方法局部变量,变量必须是final的,但在java8中final可以省略,只要代码中这个变量没有变化就行
因为new出来的对象在堆内存里,而局部变量在栈内存里,方法运行结束,立刻出栈,局部变量立刻消失
而new出来的对象在堆中持续存在直到被垃圾回收,这个对象的生命周期比栈中的局部变量长久,所以这个局部变量必须
是final,在编译的过程中会翻译成常量,被复制一份到对象里

字符串编辑尽量使用StringBuilder
StringBuilder内部是一个数组,默认长度16,在堆里面,用完就被回收掉
StringBuilder的append方法返回的是this,也就是调用方法的对象
因此append的方法可以连续调用,进行链式编程
sb.append().append().append().append();

不能在使用迭代器或forEach的时候对集合内容进行修改
否则会发生ConcurrentModificationException并发修改异常

HashSet在1.8之前是数组+链表,1.8之后是数组+红黑树。查询速度快
如果一个hash地址存入的元素超过8个,就会自动转为红黑树,以提高查询速度
调用add方法的时候先会比较hash值,不相同直接存储,相同会再调用equals,如果相同就不存储,不相同存在同一个hash地址内

List添加两次同名字符串要删两次才能删完

在自定义比较器中
o1-o2是从小到大排序
o2-o1是从大到小排序

HashTable不能存储null的key和value
HashMap可以存储null的key和value

编译时异常直接继承Exception,代码中需要进行捕捉
运行时异常继承RuntimeException
抛出编译时异常,代码必须try-catch
抛出运行时异常,代码可以不处理

多个catch捕获的异常如果有父子关系,子类异常必须在父类上面,否则会报错

在finally代码块中尽量不要写return语句

父类的异常什么样,子类也一样,子类方法的异常可以是父类异常的子异常
父类不抛出异常,子类也不能抛出异常,只能try-catch

并发:多个任务交替执行
并行:多个任务同时执行
只有多核CPU才会又并行执行,单核情况下只存在并发

同步方法的的锁对象就是this,也就是当前线程的实现类对象,静态方法的锁对象是本类的文件对象

构造方法不能递归调用,编译会报错

创建输出流可以自动创建文件,不存在的文件不会报错,但是创建输入流的时候文件不存在会报错

utf-8编码一个汉字3个字节,输出半个字符会出现乱码

\n换行对windows记事本无效,\r\n才能让记事本换行
linux换行符是\n,mac是\r

读写如果是同一个文件,写的流会创建一个新文件,把源文件覆盖,所以会导致文件为空
必须先读取文件内容,在内存中用一个List存储,关闭读流,然后再开写流

static修饰的变量不能被序列化,能被序列化的都是成员变量
transient修饰的成员变量也不能被序列化

InputStreamReaders是把文件以某个特定的字符集转换成程序里相对应的unicode格式的char类型数据,
因此无论源文件是UTF-8还是GBK,”我”字被读到程序中,int值永远是为25105
GBK:(-50-46)–>我–>25105
UTF-8:(-26-120-111)–>我–>25105

在java反射中,成员变量对象.setAccessible(true)暴力反射,可以直接获取private成员变量的值

注解本质上就是一个接口,这个接口默认继承Annotation接口

如果注解只有一个属性要赋值,而且属性名叫value,就可以直接写值

如果不把Retention定义为RUNTIME,那么在运行的时候无法通过反射得知方法上有这个注解

猜你喜欢

转载自blog.csdn.net/StarBallBigWar/article/details/82468060