- 浏览: 52986 次
- 性别:
- 来自: 佛山
最新评论
文章列表
8.54 谨慎的使用本地方法
- 博客分类:
- Effective Java
本地(native)方法可调用JVM所在的操作系统提供的方法(也可以是自行用C、C++等写的方法),使用本地方法缺点包括:
1.本地方法需要自行管理内存,如果管理不当可能导致整个应用崩溃,因此本地方法是不安全的
2.本地方法依赖操作系统,因此不是跨平台的
3.难以调试,调用本地方法较耗时(这里的调用不是指本地方法的执行时间)
建议尽可能少的使用本地方法,在部署前应进行详尽测试。不要为了少许的性能提升而使用本地方法
8.53 在反射里使用接口
- 博客分类:
- Effective Java
使用反射(reflection)创建对象,访问方法和属性的缺点包括:
1.不能在编译时进行类型检查
2.反射代码比较繁复
3.性能较低,可能比正常的方法调用低2-50倍
如果被反射的类继承了父类或实现了接口,那么可使用接口/父类类型引用此反射类,然后调用相关方法,以下代码通过反射调用ArrayList对象的add():
@Test
public void doByReflection() throws Exception{
Class<?> clazz=Class.forName("java.util.ArrayList");
...
通过接口类型引用对象将使得代码具有更高的灵活性,如下通过接口List引用Vector对象:
List<String> list=new Vector<String>();
基本原则包括:如果对象具有合适的接口类型/父类,那么应使用此接口类型/父类引用对象
如果有更合适的数据类型,应使用此类型,而不要使用String,基本原则包括:
1.String不适合代替int,float,boolean等性能更高的数据类型
2.String不适合替代枚举类型
3.String不适合替代集合类型,如应返回Address类的对象,替代返回类似“中国:广东”这样的字符串来表示地址
4.String不适合替代功能实现(capability),如要求key值对每个调用者是唯一的,并且只能由调用者访问,此情况就不适合用String作为key值,具体例子可参考原书
String在JVM里实现为不可变对象,因此在拼接字符串时,如果使用S ...
JDK5后基本数据类型都有一个对应的封装对象类型(boxed primitive),如int对应Integer。两者区别包括:
1.基本数据类型仅有数据值,而封装对象类型可能具有相同的数据值但是却是不同的对象,如:
int i=42,j=42;
System.out.println(i==j);//打印true
Integer a=Integer.valueOf(42);
Integer b=Integer.valueOf(42);
System.out.println(a==b);//打印false
2.封装对象类型具有一个特殊值null,基本数据类型不具有此值
...
不能使用float、double进行精确计算,因为浮点数本身是不精确的,如以下代码:
double result=1.00d-0.90d;
System.out.println(result);//打印0.09999999999999998
可以使用BigDecimal进行精确计算,BigDecimal可以表示任意精度的数字,如下:
BigDecimal first=BigDecimal.valueOf(1.00d);
BigDecimal second=BigDecimal.valueOf(0.90d);
BigDecimal result=first ...
8.47 使用函数库
- 博客分类:
- Effective Java
使用标准函数库可以提高开发效率,避免常见错误,并且函数库会随着JDK的发布而更新。
常见的函数库包括:
java.lang
基础库
java.util
工具库,常用到里面的集合类
java.io
IO库
java.util.concurrent
并发工具库
使用for-each循环更简洁,进而减少错误,对比如下:
Collection<String> parents=new ArrayList<String>();
Collection<String> childs=new ArrayList<String>();
for(Iterator<String> p=parents.iterator();p.hasNext();)
for(Iterator<String> c=childs.iterator();c.hasNext();)
...
最小化局部变量的可访问性可以减小发生错误的几率,局部对象占用的内存可以及时GC。基本原则包括:
1.仅在第一次使用时声明局部变量
2.声明局部变量时尽可能进行初始化
3.优先使用for循环代替while循环。以下代码局部变量i在整个sayHello()方法里都是可访问的:
Collection<String> c=new ArrayList<String>();
Iterator<String> i=c.iterator();
while (i.hasNext()) {
System.out.println ...
7.44 注释所有API元素
- 博客分类:
- Effective Java
常用的注释标签包括:
@param
注释方法参数
@param paramName
@return
注释方法返回值
@return
@throws
注释方法可能抛出的异常
@throws NullPointerException
@code
添加代码注释说明,常和<pre>一起使用
<pre>{@code index<0}</pre>
@literal
处理HTML特殊字符,使用此标签的注释不会被视为HTML文本被渲染。也可以使用数据实体如&替代特殊字符
{@literal x< ...
返回空数组或集合代替null可以避免调用者检查返回值是否为null,进而可提高开发效率。
可以每次返回同一个空数组,以避免造成性能影响,如下:
public class StringContainer {
private List<String> list=new ArrayList<String>();
private static final String[] EMPTY_STRING_ARRAY=new String[0];
public String[] getStrings(){
//如果list不包含任何元素,那 ...
7.42 谨慎的使用变长参数
- 博客分类:
- Effective Java
JDK5支持方法使用变长参数,如下:
public void sayHello(String...names){
//变长参数names可视为数组
System.out.println(names.length);
for(String name:names)
System.out.println("Hello,"+name);
}
Arrays.asList(T...a)使用了变长参数,以下代码将打印出不同的结果:
int[] values=new int[]{1,2,3};
System.out.p ...
以下类对不同的集合类型分类,classify()方法被重载:
public class CollectionClassifier {
public static String classify(Set<?> s){
return "Set";
}
public static String classify(Collection<?> c){
return "Collection";
}
}
以下测试将失败:
@Test
public void testCollec ...
7.40 谨慎设计方法签名
- 博客分类:
- Effective Java
基本原则:
1.谨慎选择方法名称,应使用简单,一致的方法名称,可参考JAVA API相关方法
2.不要提供过多的方便方法,特别是对接口方法。如果不清楚此方法是否能带来便利,则不提供
3.避免使用过长的方法参数列表,解决方法包括:
(1)把长参数列表的方法分为多个短参数的方法
(2)创建帮助类用于传入多个参数,如下
public Person(String name,String country,String city){}
//使用Address类设置多个参数值
public Person(String name,Address address){}
...
以下Period类用于表示两个日期之间的间隔:
import java.util.Date;
public class Period {
private Date start;
private Date end;
public Period(Date start,Date end){
if(start.compareTo(end)>0)
throw new IllegalArgumentException("start after end");
this.start=start;
this.end=en ...