`
lxy2330
  • 浏览: 468535 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

开发中的陷阱

    博客分类:
  • java
 
阅读更多
1.       虚拟机对字符串的处理

虚拟机是将字符串直接量(不用new声明的)对象放到一个对象池中去缓存的,第一次使用的时候会将其放入池中,如果下次有其他变量访问一摸一样的直接量的话直接从对象池中去取该直接量,而不是又再生成一个对象。一般该池中的对象都不会被垃圾回收器回收。

比如:



Java代码 
1.String str1 = "1"; 
2.String str2 = "1"; 

实际上这段代码仅仅创建了一个字符串直接对象,保存在对象池中,池中对象就是”1”。str1和str2指向了该对象池的对象位置。

2.       编译时能确定的值



在编译时就能确定的值,在编译的时候就能够确定是否创建新的对象池对象。比如:



Java代码 
1.String str3 = "suhuanzhen123"; 
2.String str4 = "suhuanzhen" + 1 + "2" + "3"; 
3.System.out.println(str3 == str4); 

实际上str3和str4在内存池中都是指向了"suhuanzhen123"这个字符串对象,所以输出时true。因为str4在编译期间就能确定值是suhuanzhen123,所以JVM不会再创建新的对象。直接从对象池中去取。

3.       在编译期间不能确定的值

如果字符串的拼接包含了函数、变量等等编译时不确定因素,那么此时就不能指向对象池中的变量了。比如



Java代码 
1.String str5 = "suhuanzhen123"; 
2.String str6 = "suhuanzhen" + "1".length() + "2" + "3"; 
3.System.out.println(str5 == str6); 

4.       在编译时就能确定值的字符串变量创建值

比如代码



Java代码 
1.String str6 = "suhuanzhen" + "1" + "2" + "3"; 

实际上仅仅创建了一个对象——suhuanzhen123,缓存到对象池。

5.       StringBuilder和StringBuffer的区别

一般在单线程的系统环境下优先使用StringBuilder,因为它是非线程安全的。而在多线程的环境下,比如Web系统,优先使用StringBuffer,因为它当中绝大部分方法都使用了synchronized进行修饰,保证了多线程环境下的线程安全问题。

6.       字符串之间的比较

用一个线程池的常量对象和一个变量、函数返回值比较直接使用==其实就可以了比如:



Java代码 
1.String jqgridparams = request.getParameter("jqgridparams"); 
2.if (jqgridparams != null) { 
3.    if ("getparams" == jqgridparams) { 
4.        //…………………… 
5.    } 
6.} 

更直观一点就是



Java代码 
1.static String getStr(){ 
2.        return "suhuanzhen123"; 
3.    } 
4. 
5.    public static void main(String[] args) { 
6.        String str7 = getStr(); 
7.        System.out.println("suhuanzhen123" == str7); 
8.         
9.    } 

输出的是true;

如果是2个字符串变量之间比较就不能用==了



Java代码 
1.String str7 = getStr(); 
2.String str8 = new String("suhuanzhen123"); 
3.System.out.println(str8 == str7); 

输出false。

应该用



Java代码 
1.System.out.println(str8.equals(str7)); 

7.       赋值语句的类型提升


























上图程序实际上就是类型自动提升发生了错误,num本身是int型,而num = num+33.567;表达式中使用了double类型的数值,那么此表达式会自动向最高级别的基本类型转型,但是呢num自身是int,会提示不能向上转换的编译错误。如果程序这么写



Java代码 
1.public static void main(String[] args) { 
2.    int num = 1; 
3.    double numDoub = num+33.567; 
4.} 

就不会报错了。

赋值运算中基本数据转型的级别从高到低排序是String->double->float->long->int->chart、short->byte。

如果运算中含有字符串变量,那么二话不说,此表达式所有的运算最后的返回值就是一个字符串了,比如



Java代码 
1.int num = 1; 
2.double numDoub = num+33.567; 
3.String str = num+numDoub+""; 

所以最高级别还是String。

8.       符合运算符中的隐式类型转换

在符合运算符中实际上存在着一个隐藏的类型转换



Java代码 
1.int sum =1; 
2.sum += 30.44; 
3.System.out.println(sum); 

实际上会输出31,如果是之前的例子



Java代码 
1.int sum =1; 
2.sum = sum+30.44; 

编译器是会报错的。那么+=实质上是什么意思呢!就是



Java代码 
1.sum += 30.44; 

等价于



Java代码 
1.sum = (int)(sum+30.44); 

也就是说符合运算符自身还隐式地包含了一个强制转型的动作。这样做有时候会失去精度以及高位段位。



Java代码 
1.short sum =9999; 
2.sum += 999999999.9999999; 
3.System.out.println(sum); 

输出-3826






















9.       泛型引起的陷阱



Java代码 
1.List list = new ArrayList(); 
2.list.add("1"); 
3.list.add(2); 
4.list.add("3q"); 
5. 
6.for (int i = 0; i < list.size(); i++) { 
7.    System.out.println(list.get(i)); 
8.} 
9. 
10.List<String> listNew = list; 
11.for (String strNew : listNew) { 
12.    System.out.println(strNew); 
13.} 

第一个循环输出无任何问题,第二个循环报出转型异常。换几话说,集合本身可以存储不同类型元素的对象的,只不过自从JDK1.5之后出现了泛型,才使我们很多人觉得集合变量仅仅能存一种类型的对象元素。泛型是为了在编译时更好的排除类型转换带来的繁琐检查。而在大多数应用中确实集合中就是同类型的元素。而泛型配合上加强的新循环,它会强制进行单一类型的转型操作。所以第二个循环的的结果就是








java.lang.Integer cannot be cast to java.lang.String



泛型还有可能引起擦除,如下:



Java代码 
1.class MyT<PK extends Number> { 
2. 
3.    private PK id; 
4. 
5.    public PK getId() { 
6.        return id; 
7.    } 
8. 
9.    public void setId(PK id) { 
10.        this.id = id; 
11.    } 
12. 
13.} 
14. 
15.public class TTrap { 
16.    /**
17.     * @param args
18.     */ 
19.    public static void main(String[] args) { 
20.        MyT<Integer> my = new MyT<Integer>(); 
21.        my.setId(100); 
22.        System.out.println(my.getId() + ":" + my.getId()); 
23.        MyT mynew = my; 
24.        System.out.println(mynew.getId() + ":" + mynew.getId()); 
25.    } 
26. 
27.} 

在mynew.getId()这一句中实际上编译器这时候仅仅将它识别为Number了,直接当做Integer使用会报错,除非强制转型方可当做Integer来使用。这里就相当于将泛型信息擦除了,程序只有到了真正运行时环境下才能把其当做Integer来用,编译期间他不认识其实质面目。Java擦除泛型信息是将该对象所有的泛型信息全部擦除掉,不仅仅是那个传入的泛型,如果此类本身也定义了其他泛型相关的方法、变量,统统没有了!



Java代码 
1.class MyTT<PK extends Number> { 
2. 
3.    private PK id; 
4. 
5.    private List<String> list; 
6. 
7.    public PK getId() { 
8.        return id; 
9.    } 
10. 
11.    public void setId(PK id) { 
12.        this.id = id; 
13.    } 
14. 
15.    public List<String> findRows() { 
16.        list = new ArrayList<String>(); 
17.        list.add("步惊云"); 
18.        list.add("聂风"); 
19.        return list; 
20.    } 
21. 
22.} 
23. 
24.    public static void main(String[] args) { 
25. 
26.        MyTT<BigInteger> myTT = new MyTT<BigInteger>(); 
27.        for (String str : myTT.findRows()) { 
28.            System.out.println(str); 
29.        } 
30.         
31.        MyTT my2 = myTT; 
32.        List listNoString = my2.findRows(); 
33.    } 






10.       遇到含有.的字符串分割成字符串数组



Java代码 
1.public static void main(String[] args) { 
2.    String str = "www.google.cn"; 
3.    String[] array = str.split("\\."); 
4.    System.out.println(array.length); 
5.} 

直接用String[] array = str.split(".");不起作用,因为”.”代表可以匹配任意字符,必须转义。






分享到:
评论

相关推荐

    单片机系统中软件陷阱技术C语言实现.pdf

    软件陷阱技术是一种有效的单片机系统中的软件抗干扰方法,它通过在程序中设置特定的指令序列,来捕获和纠正程序运行中发生的错误。这种技术在单片机系统中广泛应用于防止程序执行失控,比如当CPU受到干扰而执行非法...

    游戏学习中陷阱制作的代码

    在游戏开发中,陷阱制作是不可或缺的一部分,它能增加游戏的趣味性和挑战性。这篇内容主要探讨了在大学期中考中可能涉及的游戏学习中的陷阱制作代码。以下将详细阐述相关知识点。 1. **基础编程语言**:游戏开发...

    C指针与陷阱 中文高清版

    在开发过程中,我们还应养成良好的编程习惯,比如编写清晰的代码注释,进行充分的测试,以及利用静态分析工具和内存检测工具(如Valgrind)来查找和修复潜在的指针问题。 总的来说,理解和熟练使用C语言中的指针是...

    J2EE技术开发应用中的“陷阱”及对策

    在实际的J 2EE 项目开发中却布满大量的开发陷阱, 如模型与代码间存在隔阂, Web 开发效率不高, 中间层设计较混乱等。针对这三种陷阱应采取相应对策, 才能克服J 2EE 开发中的缺点。

    嵌入式开发中C语言的使用技巧与陷阱

    【嵌入式开发中C语言的使用技巧与陷阱】 C语言是嵌入式开发的基础,掌握好C语言的技巧和避免陷阱至关重要。以下是一些在嵌入式领域中常见的C语言知识点,以及在面试中可能会遇到的问题。 1. **预处理器...

    中小城市房地产开发的机会与陷阱.pptx

    中小城市房地产开发的机会与陷阱.pptx

    C#高手进阶之陷阱和缺陷

    8. 跨域问题:在Web开发中,处理跨域请求时,不正确的配置可能导致安全性问题或功能受限。理解CORS策略和使用方法至关重要。 9. 对象初始化和构造函数:不恰当的初始化顺序或依赖注入可能导致对象状态不一致。了解...

    程序代码实现的陷阱

    在软件开发过程中,从概念设计到最终产品的每一个步骤都是至关重要的。然而,在代码实现阶段尤其容易出现各种陷阱,这些陷阱不仅会影响软件的性能、健壮性和可维护性,还可能导致整个项目的延期甚至失败。本文旨在...

    ACE开发陷阱

    【ACE开发陷阱】这篇文章主要探讨了在使用ACE(ADAPTIVE Communication Environment)开发过程中可能遇到的问题、缺点以及解决方法。ACE是一种广泛应用于跨平台通信的C++库,它提供了丰富的网络编程接口和组件,但...

    DLL陷阱及其解决办法

    程序集清单(.manifest文件)在解决DLL陷阱中起到了至关重要的作用。它不仅列出了程序所需的依赖项,还提供了强文件名的概念,使得系统能够精确地区分不同版本的DLL文件。具体来说: 1. **客户端程序集清单**:通常...

    Android平台游戏软件开发实际上是陷阱.pdf

    文档提到的“陷阱”实际上反映了Android游戏开发中存在的各种挑战,包括市场碎片化、盈利难题、技术更新频繁、市场竞争激烈以及盗版问题等。这些挑战要求开发者必须具备更加全面的技能和策略,才能在Android游戏开发...

    采用软件陷阱对程序“跑飞”的软件处理实例

    在IT行业的嵌入式系统开发领域,程序“跑飞”是一个常见的问题,它指的是程序运行过程中,由于各种原因(如硬件故障、软件错误等),导致CPU执行指令的流程偏离正常路径,进入未知或不可控的状态。为了有效应对这一...

    C语言缺陷和陷阱[参照].pdf

    在这篇文章中,我们将介绍C语言中的常见缺陷和陷阱,以及如何避免它们。 首先,让我们来讨论C语言的词法分析器(lexical analyzer)。词法分析器的作用是检查组成程序的字符序列,并将它们划分为记号(token)。...

    需求陷阱 Requirement Traps

    在软件开发过程中,需求分析阶段至关重要。正如卡尔·E·韦格斯(Karl E. Wiegers)在其著作中所强调的那样,高质量的软件始于卓越的需求。忽视需求开发与管理流程往往会导致项目的挫折与失败。本文将详细介绍韦格斯...

    C语言学习的一些陷阱

    2. **使用IDE的辅助功能**:现代集成开发环境(IDE)如Visual Studio Code、Eclipse等提供了代码提示和错误高亮功能,可以帮助开发者及时发现这类错误。 3. **代码审查**:定期进行代码审查,让同事或团队成员帮助检查...

    C语言缺陷与陷阱(笔记).txt

    C语言作为一门历史悠久且应用广泛的编程语言,在实际开发过程中,存在着不少容易让人忽视的缺陷和陷阱。本文将对这些缺陷和陷阱进行详细的分析,并提供相应的解决方案。 #### 二、具体缺陷与陷阱 ##### 1. 表达式...

    Delphi 陷阱大全.pdf

    为了帮助程序员们提高开发效率,避免不必要的错误,减少软件开发中的BUG,从而提高软件产品的质量,相关书籍《Delphi陷阱大全》应运而生。 本书由孙晓刚编写,出版于2013年10月1日。作者序中提到,软件开发中的错误...

    aras12开发手册说明书

    文档还应该包含关于二次开发的准则,比如最佳实践、常见陷阱和问题解决方法。这些内容能够帮助开发人员提高工作效率,减少在二次开发过程中可能遇到的错误和问题。 整体来看,Aras Innovator 12开发手册是一本深入...

    Java面试中的陷阱

    Java面试中的陷阱往往涉及到对语言核心概念的深度理解,这些陷阱涵盖了从基本语法特性到高级设计模式的应用。面试官通常会通过一些看似简单但实际上需要深入理解的问题来测试候选人的技能和经验。 首先,我们来看看...

Global site tag (gtag.js) - Google Analytics