资讯专栏INFORMATION COLUMN

java常见十大误区

yintaolaowanzi / 652人阅读

摘要:根据拇指规则,最佳做法应该是尽量减少属性的访问级别。通常的,可变对象可用来避免产生过多的对象。如果类中定义了构造函数,那么编译器将不会给它插入默认构造函数。

1、转化数组为ArrayList

通常开发者转化数组为ArrayList的方式为

List list = Arrays.asList(arr);

Arrays.asList()会返回一个ArrayList,而这个ArrayList是Arrays类的静态内部类,不是java.util.ArrayList。

这个类有get()、set()和contains()方法,但却没有任何可以添加元素的方法。正确的做法可以这样做

ArrayList arrayList = new ArrayList(Arrays.asList(arr));
2、检查数组里面是否包含某个元素

部分开发者会这样实现

return new HashSet(Arrays.asList(arr)).contains(targetValue);

结果是对的,但是没有必要转化为Set,这反而会花费更多时间,可以简单这样实现

return Arrays.asList(arr).contains(targetValue);

或者

for(String s: arr){
    if(s.equals(targetValue))
        return true;
}
return false;

补充:第一种相比第二种可读性会高一些。

3、数组中循环删除元素

分析一下下列代码:

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
for (int i = 0; i < list.size(); i++) {
    list.remove(i);
}
System.out.println(list);

输出结果为:

[b, d]

因为当数组删除一个元素后,它的长会缩小,index相当于向后移动一位,这是个严重的问题。当你想通过index来删除多个元素时候,这种方法是不可取的。

你也许知道用迭代器来删除是没问题的,并且java中有一类for语句原理就是使用迭代器。但实际你想用这类for语句来代替迭代器进行删除也是不行的,如下代码

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
 
for (String s : list) {
    if (s.equals("a"))
        list.remove(s);
}

将会抛出ConcurrentModificationException异常。

如下代码才是正确的

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c", "d"));
Iterator iter = list.iterator();
while (iter.hasNext()) {
    String s = iter.next();
 
    if (s.equals("a")) {
        iter.remove();
    }
}

next()必须在remove()之前被调用。而在for循环中,编译器会在元素被remove之后调用next(),因此就会抛出ConcurrentModificationException异常。

4、hashtable和hashmap

java中有两类,HashTable和HashMap,两者的数据结构是一致的(哈希表),然后两者的区别是:HashTable是同步的。

所以HashTable是线程安全的,HashMap不是线程安全的。

提示:也可以使用ConcurrentHashMap来保证线程安全,ConcurrentHashMap使用分段锁(segment)的原理,效率上会高一些。

5、集合中原生态类型(raw type)的使用

在java中,开发者通常把原生态类型(raw type)通常和无界通配符类型(unbounded wildcard type)弄混。拿Set来举例子,Set是原生态类型,而Set是无界通配符类型。

如下代码使用了原生态类型

public static void add(List list, Object o){
    list.add(o);
}
public static void main(String[] args){
    List list = new ArrayList();
    add(list, 10);
    String s = list.get(0);
}

代码将会抛出异常

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at ...

原生态类型会越过泛型的校验,是不安全的。

6、访问级别

有的开发者将类某些属性直接定义为public,这很容易通过外部访问,但绝对是很差的设计。根据拇指规则,最佳做法应该是尽量减少属性的访问级别。

7、LinkList vs ArrayList

很多开发者都习惯使用ArrayList,可能ArrayList相对来说比较熟悉的缘故,其实ArrayList和LinkList还是存在很大的区别。简而言之,LinkList应该在有大量增删操作且无随机访问操作时候使用。

8、可变(mutable) vs 不可变(immutable)

不可变对象有很多优点,比如简单、安全等。但对于多个值则需要多个不同的对象来表示,对象过多时,会消耗很多的GC资源。

通常的,可变对象可用来避免产生过多的对象。如下代码中使用了不可变对象,那么执行过程中将会产生很多的String,消耗很多时间和cpu性能。如果换成可变对象(StringBuilder等),将会好很多。

String result="";
for(String s: arr){
    result = result + s;
}
9、父子类的构造函数
    class Super {
        String s;

        public Super(String s) {
            super();
            this.s = s;
        }

    }

    class Sub extends Super {

        public Sub(String s) {
        }

        public Sub() {

        }
    }

上述代码会出错,是因为父类默认构造函数没有定义。在java中,如果一个类没有定义构造函数,则编译器会给它构造默认的无参构造函数。如果类中定义了构造函数,那么编译器将不会给它插入默认构造函数。这个正是上述父类的遇到的情况。

在子类中的两个构造函数中,编译器试图插入父类的默认构造函数super(); ,然而并未找到,因此编译出错。

10、"" or Constructor

字符串可以通过两种方式建立

//1. 直接引用
String x = "abc";
//2. 使用构造函数
String y = new String("abc");

两者却别可通过如下代码阐明

String a = "abcd";
String b = "abcd";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True
 
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d);  // False
System.out.println(c.equals(d)); // True

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70885.html

相关文章

  • 使用 Spring Framework 时常犯的十大错误

    摘要:常见错误五多线程处理不当不管是桌面应用还是应用,无论是还是,多线程都是很难破解的。当然,理想情况下,你也希望完全避免多线程错误。同样,不存在那种一刀切的方法,但这有一些调试和防止多线程错误的实际考虑因素避免全局状态首先,牢记全局状态问题。 Spring 可以说是最流行的 Java 框架之一,也是一只需要驯服的强大野兽。虽然它的基本概念相当容易掌握,但成为一名强大的 Spring 开发者...

    luckyw 评论0 收藏0
  • 2021年游戏项目的十大编程语言:C++、Java、C#均上榜

    摘要:月日,发布文章,介绍了年游戏项目的十大编程语言。无疑是游戏项目的最佳编程语言之一。是和等游戏引擎所使用的主要编程语言。对于游戏开发者来说,是最友好最灵活的编程语言之一。作为游戏项目的最佳视频游戏编程语言之一,正在赢得属于自己的一份荣耀。 ...

    不知名网友 评论0 收藏0
  • 十大经典排序算法总结(Javascript描述)

    摘要:算法描述冒泡排序是一种简单的排序算法。算法描述和实现一般来说,插入排序都采用在数组上实现。平均情况希尔排序年发明第一个突破的排序算法是简单插入排序的改进版它与插入排序的不同之处在于,它会优先比较距离较远的元素。 前言 读者自行尝试可以想看源码戳这,博主在github建了个库,读者可以Clone下来本地尝试。此博文配合源码体验更棒哦~~~ 个人博客:Damonare的个人博客 原文地址:...

    Binguner 评论0 收藏0
  • Nginx反向代理跨域基本配置与常见误区

    摘要:同时由于跨域了,就想利用的反向代理去处理一下跨域,但是在解决问题的同时,发现网上有些方案的确是存在一些问题,在这里总结一下基本配置,也聊一下常见的配置问题。 最近公司前后端分离,前端独立提供页面和静态服务很自然的就想到了用nginx去做静态服务器。同时由于跨域了,就想利用nginx的反向代理去处理一下跨域,但是在解决问题的同时,发现网上有些方案的确是存在一些问题,在这里总结一下基本配置...

    lindroid 评论0 收藏0
  • Nginx反向代理跨域基本配置与常见误区

    摘要:同时由于跨域了,就想利用的反向代理去处理一下跨域,但是在解决问题的同时,发现网上有些方案的确是存在一些问题,在这里总结一下基本配置,也聊一下常见的配置问题。 最近公司前后端分离,前端独立提供页面和静态服务很自然的就想到了用nginx去做静态服务器。同时由于跨域了,就想利用nginx的反向代理去处理一下跨域,但是在解决问题的同时,发现网上有些方案的确是存在一些问题,在这里总结一下基本配置...

    JasonZhang 评论0 收藏0

发表评论

0条评论

yintaolaowanzi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<