JAVA 有点儿冷

简单的一些不怎么用的java知识总结。


1.Double类型

java浮点数分3类,正无穷大(Double.POSITIVE_INFINITY),负无穷大(Double.NEGATIVE_INFINITY)和非数字(Double.NaN)。判断用Double.is*** 静态方法。

2. UTF-16

java中,用UTF-16编码字符。对于我们常用的所谓的基本的多语言级别的代码,用16位表示一个字符,称为代码单元code unit);而特殊的辅助字符,则用两个16位表示,即两个代码单元。

所以,对字符串中每个字符的便利和提取相对复杂一些(尽管我们并不怎么需要便利字符串)。字符串中,每个字符称为代码点,而一个代码点可能占1个代码单元,也可能占两个代码单元。String的length()方法返回的是代码单元的数量,charAt(n)返回的是n位置上代码单元的字符。而String的以codePoint开头的方法才是针对代码点的。比如codePointCount(0,length)返回0到length中字符串中代码点的个数。codePointAt(i)返回i位置的codePoint,即字符。 所以遍历字符,需要

for(int i;i<str.length();) {
int cp = str.getCodePointAt(i);
if(Character.isSupplymentaryCodePoint(cp)) i+=2;
else i++;
...
}


3.一种将Date转化为String的方法。

String time = String.format("%tY-%<tm-%<td %<tH:%<tM:%<tS", new Date());

输出为 : 2014-12-13 23:32:48

这里,%t* 表示一种时间,比如%tY表示4位时间,2014;%<* 表示后面的参数被多次使用,即new Date()也是后面几个%X的参数。

4、单利模式一定安全?

其实,可以通过反射调用私有构造函数。防治办法是在私有方法里抛出异常。

5.终结方法

终结方法虽然存在,但未必好用。一般,其运行时不可预测的,而且会造成程序性能下降,调用此方法回收内存是不可行的。一个对象的终结方法和整个JVM的GC的线程拥有的优先级很低,且其调用是不被保证的。

其实,jvm提供了强大的垃圾回收机制,内存管理,就托管给JVM就可以了,我们的干预顶多是在代码和一些JVM参数上做文章。当然,一般程序中还会涉及非内存的资源,比如网络连接等,这些资源的释放应该放在finally中进行。

同时,System.gc和System.runFinalization两个方法只能增加gc执行的可能性,并不能确保gc发生。而使用它们,却会造成系统性能的很大损失。

《Effctive Java》中认为两种情况因可以使用终结方法,一种是对于链接的资源,如果使用了终结方法,那么总会被释放,但是明显这会引起性能的问题,而正确的释放仍然是在finally中释放;另一种情况是针对本地对象。虽然Java是跨平台的,但是Java的实现并不是跨平台的,不同平台会绑定不同的java本地对象,而操作这些对象的普通java对象的回收并不会引起本地对象的资源回收(我觉得这是android手机慢的一个原因)。如果本地对象与外部重要资源关联,那么应该在finally中释放,不然,用终结方法释放是合适的。

但是有一点需要注意,当对象重写了终结方法,一定要调用父类的终结方法,不然父类的终结方法将得不到执行。

6.静态工厂方法创建对象的缺点

如果没有共有的构造方法,那么这个类相当于不能被其他类继承,因为子类必须可以调用父类的构造方法,否则无法实例化;但是有工厂,又有方法,就有些混乱了。同时,静态方法其实也是普通的方法,如果说有区别,那区别也只是工厂方法一定会返回一个构造函数构造的对象。

例如下面例子:

/**
 * 想继承这个类,子类的构造函数必须调用SuperClassHelper(int i)。
 *
 */
public class SuperClassHelper {
	@SuppressWarnings("unused")
	private SuperClassHelper() {
	}

	public SuperClassHelper(int i) {
	}
}

7.java的内存泄露

java提供了良好的GC机制,但是java毕竟是计算机语言,无法智能的对一切不可用的垃圾进行回收。所以,其实JVM仍然可能发生内存泄露。一种情况就是一直保持着对过期对象的引用,比如对数组中对象不清理,而只是移动表示其范围的下标,或者对HashMap不停添加新的键值对进去,但对于过期和应该删除的键值对不做处理。这样,逻辑上无用的对象是不必要继续保留的,但是却会一直留在JVM中,这边导致了内存泄露。另一种导致内存泄露的情况是缓存,缓存引起的内存溢出其实也是没有清理不用的对象,特别的地方是缓存不用的对象并不像一般的对象那么明显。对于前一种情况,应该采取显示的清理方法,比如 elements[i]=null;对于后一种情况,可以采用弱引用,比如WeakedHashMap。

8.Object自身方法

equals和hashCode方法关注对象实例的相同的域。equals关系要求满足自反,对称,传递和一致。equals的对象之间的hashCode方法返回相同的int。重写equals方法必须重写hashCode方法,否则很多基于hashCode方法的行为将出现想象不到的结果,比如HashMap,其在找桶的阶段调用hashCode方法,而在找到桶后,确定对象的阶段调用equals,显然这两个方法有紧密的联系。对于hashCode方法,冗余的域可以不加入计算,这样可以减少计算量。

clone方法是object的一个受保护的方法,cloneable接口表示这个类是可复制的,它决定了object中clone方法的行为:逐域复制。意义是,clone放回一个新的对象,这个新对象在jvm堆上,与原对象同类型,且equals返回true。clone并没有调用构造器。clone的本意是全新的,但是默认情况下是浅复制,深复制需要手动重写方法实现。见这里。顺便提一点,comparable最好保持compareTo和equals是一致的。因为对于有序集合,比如TreeSet,其调用的是comrateTo,而对于无序的HashSet,则调用equals。

9.abstract interface

java中可以使用奇怪的abstract interface,但abstract为什么interface?先看例子:

public abstract interface AbsInt {
	void fun();

	abstract int abfun();
}
public class RealClass implements AbsInt {

	@Override
	public void fun() {

	}

	@Override
	public int abfun() {
		return 0;
	}

}
这样的组合是可以的,但是没必要。interface本身“就是 abstract”,其方法隐式为abstract。说明了一个abstract interface其实还是interface。

10.java的静态块

java静态代码块只会执行一次;但是什么时候执行?先看例子:

public class CanStaticBlockWork {
	private static class A {
		static int CONST = 1;

		static {
			System.out.println("A No. 1 block");
		}
		static {
			CONST = 10;
			System.out.println("A No. 2 block");
		}
		static {
			CONST = 10;
			System.out.println("A No. 3 block");
		}

	}

	private static class B extends A {
		static {
			System.out.println("B static");
		}
	}

	public static void main(String[] args) {
		System.out.println(B.CONST);
		new B();
	}
}
输出:

A No. 1 block
A No. 2 block
A No. 3 block
10
B static
如果去掉new B(); 输出结果呢?如下:

A No. 1 block
A No. 2 block
A No. 3 block
10

如果上面代码改成:

public class CanStaticBlockWork {
	private static class A {
		static int CONST = 1;

		static {
			System.out.println("A No. 1 block");
		}

	}

	private static class B extends A {
		static {
			System.out.println("B static");
		}
	}

	public static void main(String[] args) {
		System.out.println(B.CONST);
//		new B();
	}
}
输出为:

A No. 1 block
1

如果将CONST改成final呢?结果为:

1

-----------------------------

上面做了这么多实验说明了什么?静态代码块在类加载的时候,并不一定会执行,只有在使用到类的静态方法或者访问静态域,或者实例化对象(其实实例化本身要求类的静态属性方法加载成功)的时候,才会执行静态代码块。而成为final static的时候,为什么不会触发静态代码块,我觉得是final变量在jvm中成为常量池中的变量,使用final变量不会引发静态内容的加载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值