改善Java程序的151个建议 笔记

来源:互联网 发布:知乎 北京 中科院 编辑:程序博客网 时间:2024/06/05 16:22

四舍六入五取偶

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。

包装类型,基本类型的函数参数,可以构成重载。

包装类型,不能自动加宽。

随机数种子若相同,即使实例不同,也能产生相同的随机数。

 

不要覆写static方法:覆写的static方法在调用时会调用表面类型的方法,而非实际类型的,故多态失效。

//执行顺序:(优先级从高到低。)静态代码块>main方法>构造代码块>构造方法。

其中静态代码块只执行一次。构造代码块在每次创建对象是都会执行。

//构造代码块:直接在类中定义且没有加static关键字的代码块称为{}构造代码块

 

匿名类的构造函数式构造代码块,可以有多个。

   List l1 = new ArrayList();  //普通的ArrayList对象

   List l2 = new ArrayList(){};  //一个派生于ArrayList的匿名类的对象

   List l3 = new ArrayList(){{}};//一个派生于ArrayList的匿名类的对象,且有构造代码块

 

内部类:(重点)

普通内部类不能声明static的变量,函数。

静态内部类只能访问外部类的静态属性及方法。

 

A:内部类可以直接访问外部类中的成员(包括private),因为内部类持有外部类的引用,格式为:外部类名.this

B:外部类要想访问内部类的成员,必须创建对象访问

内部类的访问格式:

A:当内部类定义在外部类的成员位置,而且非私有,则可以在其他外部类中直接建立内部类对象。

格式:外部类名.内部类名  变量名 = new 外部类对象.内部类对象

如:Outer.Innerin = new Outer().new Inner() 连续new外,new内

B:当内部类在外部类成员位置,且被static修饰时

newOuter.Inner().function();

newOuter.Inner.function();  只new外

 

匿名内部类(局部内部类的简写)

(1)前提:继承一个类或者实现一个接口

(2)格式:

new 父类名或者接口名()

  {

         重写父类方法或者实现接口中的方法。              也可以自定义其他方法。

};

 

三元操作符的类型必须一致。

变长参数的函数可以重载,但是应该避免。因为编译器一般会“从简调用”。

反序列化时,构造函数不会执行;通过函数返回值赋值的变量也不会重新赋值。即反序列化时,不会有函数调用。

 

new String() instance of String //ok

'A' instance of charactor //wrong ,instanceof 不能用于基本类型

"A" instance of charactor //ok

null instance of Object //wrong , null木有类型

(String)null instance of Object // wrong ,null木有类型

 

Buffer,Table, Vector 是线程安全的。不必考虑到线程同步问题,我们应该优先使用Builder,Map,List类;

枚举类型可以有自定义函数(静态,非静态),但是不能被继承。

泛型类型在编译时会有“泛型擦除”,故泛型参数的函数不能构成重载。

List<String>,List<Integer>,List<T>被擦除后类型为List。

List<String>[] 擦除后为List[]

List<? extends E>, List<? superE> 擦除后为List<E>

 

协变:窄类型替换宽类型;

逆变:宽类型替换窄类型;

泛型不适用里氏替换原则(有使用父类型对象的地方都可以换成子类型对象)。泛型的参数必须固定,即使是父类子类也不能。

List<Integer> 不是List<Number>的子类型;

List<Integer> 不是List<?extends Integer> 的子类型;

List<Integer>不是 List<?super Integer> 的子类型;

 

importstatic语句导入一个类中的某个静态方法或所有静态方法, 静态导入后,静态方法前面就不用写类名.方法的方式类调用.

assert如果该值为false,说明程序已经处于不正确的状态下,assert将给出警告或退出。

java中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露.

final的instant variable没有defaultvalue,必须在声明时赋值。

 

(重点)

方法区存放了一些常量、静态变量、类信息等,可以理解成class文件在内存中的存放位置。

永久代也就是我们通常说的方法区. java8之后 Hotspot 虚拟机从堆中彻底删除了永久代。

java常量池技术:java中的常量池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复创建相等变量时节省了很多时间。常量池其实也就是一个内存空间,不同于使用new关键字创建的对象所在的堆空间。

静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。

运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

运行时常量池中的常量,基本来源于各个class文件中的常量池。

方法区物理上存在于堆里,而且是在堆的持久代里面;但在逻辑上,方法区和堆是独立的。

一般说堆的持久代就是说方法区,因为一旦JVM把方法区(类信息,常量池,静态字段,方法)加载进内存以后,这些内存一般是不会被回收的了。

阅读全文
0 0