四虎影院网址多少
栏目分类
热点资讯
桃花影院

你的位置:四虎影院网址多少 > 桃花影院 > 桃花影院 Java 开发中十个让人头疼的 Bug

桃花影院 Java 开发中十个让人头疼的 Bug

发布日期:2021-10-12 00:37    点击次数:194

谁人谁,今天又写 bug 了,没错,他说的相通就是吾。。。。。。青青草天堂影院

行为 Java 开发,吾们在写代码的过程中不免会产生各栽奇思妙想的 bug ,有些 bug 就挺让人无奈的,比如说各栽空指针变态,在 ArrayList 的迭代中进走删除操作引发变态,数组下标越界变态等。

倘若你不仔细望到同事的代码展现了吾所描述的这些 bug 后,那你就把吾这篇文章甩给他!!!你甩给他一篇文章,并让他关注了一波 cxuan,你会收获他在后面像是喜出望外并满眼尊重大神的现在光。

废话不多说,下面进入正题。

舛讹一:Array 转换成 ArrayList

Array 转换成 ArrayList 还能出错?这是哪个笨。。。。。。

等等,你先别发急说,先来望望是怎么回事。

倘若要将数组转换为 ArrayList,吾们清淡的做法会是云云

List<String> list = Arrays.asList(arr); 

Arrays.asList() 将返回一个 ArrayList,它是 Arrays 中的私有静态类,它不是 java.util.ArrayList 类。如下图所示

Arrays 内部的 ArrayList 只有 set、get、contains 等手段,但是异国能够像是 add 这栽能够使其内部组织进走转折的手段,因此 Arrays 内部的 ArrayList 的大幼是固定的。

倘若要创建一个能够增补元素的 ArrayList ,你能够行使下面这栽创建手段:

ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr)); 

由于 ArrayList 的组织手段是能够授与一个 Collection 荟萃的,因此这栽创建手段是可走的。

舛讹二:检查数组是否包含某个值

检查数组中是否包含某个值,片面程序员频繁会这么做:

Set<String> set = new HashSet<String>(Arrays.asList(arr)); return set.contains(targetValue); 

这段代码固然没错,但是有额外的性能消耗,平常情况下,不必将其再转换为 set,直接这么做就益了:

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

或者行使下面这栽手段(穷举法,循环判定)

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

上面第一段代码比第二段更具有可读性。

舛讹三:在 List 中循环删除元素

这个舛讹吾自夸许多幼友人都清新了,在循环中删除元素是个禁忌,有段时间内吾在审阅代码的时候就爱望团队的其他幼友人有异国犯这个舛讹。

说到底,为什么不克这么做(荟萃内删除元素)呢?且望下面代码

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

这个输出效果你能想到么?是不是蠢蠢欲动想试一波了?桃花影院

答案其实是 [b,d]

为什么只有两个值?吾这不是循环输出的么?

其实,在列外内部,当你行使外部 remove 的时候,一旦 remove 一个元素后,其列外的内部组织会发生转折,一路先荟萃总容量是 4,remove 一个元素之后就会变为 3,然后再和 i 进走比较判定。。。。。。因此只能输出两个元素。

你能够清新行使迭代器是精确的 remove 元素的手段,你还能够清新 for-each 和 iterator 这栽做事手段相通,因此你写下了如下代码

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

然后你足够自夸的 run xxx.main() 手段,效果。。。。。。ConcurrentModificationException

为啥呢?

那是由于行使 ArrayList 中外部 remove 元素,会造成其内部结议和游标的转折。

在阿里开发规范上,也有不要在 for-each 循环内对元素进走 remove/add 操作的表明。

因此行家要行使 List 进走元素的增补或者删除操作,肯定要行使迭代器进走删除。也就是

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

.next() 必须在 .remove() 之前调用。在 foreach 循环中,编译器会在删除元素的操作后调用 .next(),导致ConcurrentModificationException。

舛讹四:Hashtable 和 HashMap

这是一条算法方面的规约:依照算法的约定,Hashtable 是数据组织的名称,但是在 Java 中,数据组织的名称是 HashMap,Hashtable 和 HashMap 的主要区别之一就是 Hashtable 是同步的,因此许多时候你不必要 Hashtable ,而是行使 HashMap。

舛讹五:行使原首类型的荟萃

这是一条泛型方面的收敛:

在 Java 中,原首类型和无界通配符类型很容易同化在一首。以 Set 为例,Set 是原首类型,而 Set 是无界通配符类型。

比如下面行使原首类型 List 行为参数的代码:

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

这段代码会抛出 java.lang.ClassCastException 变态,为啥呢?

行使原首类型荟萃是比较危险的,由于原首类型会跳过泛型检查而且担心然,Set、Set 和 Set 存在重大的迥异,而且泛型在行使中很容易造成类型擦除。

行家都清新,Java 的泛型是假泛型,这是由于 Java 在编译期间,一切的泛型新闻都会被擦失踪,精确理解泛型概念的主要前挑是理解类型擦除。Java 的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型新闻的,行使泛型的时候添上类型参数,在编译器编译的时候会往失踪,这个过程成为类型擦除。

如在代码中定义List和List等类型,在编译后都会变成List,JVM 望到的只是List,而由泛型附添的类型新闻对 JVM 是望不到的。Java 编译器会在编译时尽能够的发现能够出错的地方,但是照样无法在运走时刻展现的类型转换变态的情况,类型擦除也是 Java 的泛型与 C++ 模板机制实现手段之间的主要区别。

比如下面这段示例:

public class Test {      public static void main(String[] args) {          ArrayList<String> list1 = new ArrayList<String>();         list1.add("abc");          ArrayList<Integer> list2 = new ArrayList<Integer>();         list2.add(123);          System.out.println(list1.getClass() == list2.getClass());     }  } 

在这个例子中,吾们定义了两个ArrayList数组,不过一个是ArrayList泛型类型的,只能存储字符串;一个是ArrayList泛型类型的,只能存储整数,末了,吾们始末list1对象和list2对象的getClass()手段获取他们的类的新闻,末了发现效果为true。表明泛型类型String和Integer都被擦除失踪了,只剩下原首类型。

因此,最上面那段代码,把 10 增补到 Object 类型中是十足能够的,然而将 Object 类型的 "10" 转换为 String 类型就会抛出类型转换变态。

舛讹六:访问级别题目

吾自夸大片面开发在设计 class 或者成员变量的时候,都会浅易强横的直接声明 public xxx,这是一栽糟糕的设计,声明为 public 就很容易赤身裸体,云云对于类或者成员变量来说,都存在肯定危险性。

舛讹七:ArrayList 和 LinkedList

哈哈哈,ArrayList 是吾见过程序员行使频次最高的工具类,异国之一。

当开发人员不清新 ArrayList 和 LinkedList 的区别时,他们频繁行使 ArrayList(其实实际上,就算清新他们的区别,他们也不必 LinkedList,由于这点性能不值一挑),由于望首来 ArrayList 更熟识。。。。。。

但是实际上,ArrayList 和 LinkedList 存在重大的性能迥异,简而言之,倘若增补/删除操作大量且随机访问操作不是许多,则答首选 LinkedList。倘若存在大量的访问操作,那么首选 ArrayList,但是 ArrayList 不正当进走大量的增补/删除操作。

舛讹八:可变和不可变

不可变对象有许多益处,比如浅易、坦然等。但是不可变对象必要为每个迥异的值分配一个单独的对象,对象不具备复用性,倘若这类对象过多能够会导致垃圾回收的成本很高。在可变和不可变之间进走选择时必要有一个均衡。

清淡来说,可变对象用于避免产生过多的中心对象。比如你要连接大量字符串。倘若你行使一个不可变的字符串,你会产生许多能够立即进走垃圾回收的对象。这会铺张 CPU 的时间和精力,行使可变对象是精确的解决方案(例如 StringBuilder)。如下代码所示:

String result=""; for(String s: arr){  result = result + s; } 

因此,精确选择可变对象照样不可变对象必要庄重抉择。

舛讹九:组织函数

最先望一段代码,分析为什么会编译不始末?

发生此编译舛讹是由于不决义默认 Super 的组织函数。在 Java 中,倘若一个类异国定义组织函数,编译器会默认为该类插入一个默认的无参数组织函数。倘若在 Super 类中定义了组织函数,在这栽情况下 Super(String s),编译器将不会插入默认的无参数组织函数。这就是上面 Super 类的情况。

要想解决这个题目,只必要在 Super 中增补一个无参数的组织函数即可。

public Super(){     System.out.println("Super"); } 
舛讹十:到底是行使 "" 照样组织函数

考虑下面代码:

String x = "abc"; 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 

这就是一个典型的内存分配题目。

后记

今天吾给你汇总了一下 Java 开发中常见的 10 个舛讹,固然比较浅易,但是很容易无视的题目,细节收获完善,望望你还会不会再犯了,倘若再犯,嘿嘿嘿。

本文转载自微信公多号「程序员cxuan」,能够始末以下二维码关注。转载本文请有关程序员cxuan公多号。

【编辑保举】桃花影院

鸿蒙官方战略配相符共建——HarmonyOS技术社区 苹果行使程序开发商正开发新柔件:竭力规避“苹果税” 如何修复Windows 11升级后展现Windows 10义务栏的Bug? Java、Golang项现在基于kubernetes集群CICD实践案例【Gitlab工具链】 TIOBE 10 月榜单:Python 夺冠,Java 和 C 永远霸权终结 摊牌了,行为开发者,吾频繁用这14个 Github 偷偷学习

友情链接:

Powered by 四虎影院网址多少 @2013-2021 RSS地图 HTML地图