`
changyehappy
  • 浏览: 18144 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java常识

 
阅读更多
http://wenku.baidu.com/view/0d4f563c0912a21614792928.html

Java基础复习笔记03我们不太注意的陷阱  刘岩  Email:suhuanzheng7784877@163.com  1. 虚拟机对字符串的处理  虚拟机是将字符串直接量(不用new声明的)对象放到一个对象池中去缓存的,第一次使用的时候会将其放入池中,如果下次有其他变量访问一摸一样的直接量的话直接从对象池中去取该直接量,而不是又再生成一个对象。一般该池中的对象都不会被垃圾回收器回收。 比如:  String str1 = "1"; String str2 = "1";  实际上这段代码仅仅创建了一个字符串直接对象,保存在对象池中,池中对象就是”1”。str1和str2指向了该对象池的对象位置。 2. 编译时能确定的值  在编译时就能确定的值,在编译的时候就能够确定是否创建新的对象池对象。比如:  String str3 = "suhuanzhen123";  String str4 = "suhuanzhen" + 1 + "2" + "3"; System.out.println(str3 == str4);  实际上str3和str4在内存池中都是指向了"suhuanzhen123"这个字符串对象,所以输出时true。因为str4在编译期间就能确定值是suhuanzhen123,所以JVM不会再创建新的对象。直接从对象池中去取。 3. 在编译期间不能确定的值  如果字符串的拼接包含了函数、变量等等编译时不确定因素,那么此时就不能指向对象池中的变量了。比如  String str5 = "suhuanzhen123";  String str6 = "suhuanzhen" + "1".length() + "2" + "3"; System.out.println(str5 == str6);    4. 在编译时就能确定值的字符串变量创建值  比如代码  String str6 = "suhuanzhen" + "1" + "2" + "3";  实际上仅仅创建了一个对象——suhuanzhen123,缓存到对象池。 5. StringBuilder和StringBuffer的区别  一般在单线程的系统环境下优先使用StringBuilder,因为它是非线程安全的。而在多线程的环境下,比如Web系统,优先使用StringBuffer,因为它当中绝大部分方法都使用了synchronized进行修饰,保证了多线程环境下的线程安全问题。 6. 字符串之间的比较  用一个线程池的常量对象和一个变量、函数返回值比较直接使用==其实就可以了比如:  String jqgridparams = request.getParameter("jqgridparams"); if (jqgridparams != null) {   if ("getparams" == jqgridparams) {  文档冲亿季,好礼乐相随mini ipad移动硬盘拍立得百度书包 2 / 14      //„„„„„„„„  }  }  更直观一点就是   static String getStr(){   return "suhuanzhen123";   }    public static void main(String[] args) {   String str7 = getStr();    System.out.println("suhuanzhen123" == str7);       }  输出的是true;  如果是2个字符串变量之间比较就不能用==了  String str7 = getStr();  String str8 = new String("suhuanzhen123"); System.out.println(str8 == str7);  输出false。 应该用  System.out.println(str8.equals(str7));   7. 赋值语句的类型提升  上图程序实际上就是类型自动提升发生了错误,num本身是int型,而num = num+33.567;表达式中使用了double类型的数值,那么此表达式会自动向最高级别的基本类型转型,但是呢num自身是int,会提示不能向上转换的编译错误。如果程序这么写   public static void main(String[] args) {   int num = 1;    double numDoub = num+33.567;    }  就不会报错了。  赋值运算中基本数据转型的级别从高到低排序是String->double->float->long->int->chart、short->byte。  如果运算中含有字符串变量,那么二话不说,此表达式所有的运算最后的返回值就是一个字符串了,比如    int num = 1;    double numDoub = num+33.567;     String str = num+numDoub+"";  所以最高级别还是String。  8. 符合运算符中的隐式类型转换   3 / 14    在符合运算符中实际上存在着一个隐藏的类型转换    int sum =1;   sum += 30.44;    System.out.println(sum); 实际上会输出31,如果是之前的例子    int sum =1;     sum = sum+30.44;  编译器是会报错的。那么+=实质上是什么意思呢!就是 sum += 30.44; 等价于  sum = (int)(sum+30.44);  也就是说符合运算符自身还隐式地包含了一个强制转型的动作。这样做有时候会失去精度以及高位段位。  short sum =9999;  sum += 999999999.9999999; System.out.println(sum);  输出-3826  9. 泛型引起的陷阱  List list = new ArrayList(); list.add("1"); list.add(2); list.add("3q");   for (int i = 0; i < list.size(); i++) {  System.out.println(list.get(i));  }   List<String> listNew = list; for (String strNew : listNew) {  System.out.println(strNew); }  第一个循环输出无任何问题,第二个循环报出转型异常。换几话说,集合本身可以存储不同类型元素的对象的,只不过自从JDK1.5之后出现了泛型,才使我们很多人觉得集合变量仅仅能存一种类型的对象元素。泛型是为了在编译时更好的排除类型转换带来的繁琐检查。而在大多数应用中确实集合中就是同类型的元素。而泛型配合上加强的新循环,它会强制进行单一类型的转型操作。所以第二个循环的的结果就是 java.lang.Integer cannot be cast to java.lang.String 泛型还有可能引起擦除,如下:  class MyT<PK extends Number> {   private PK id;   public PK getId() {     return id;   4 / 14     }    public void setId(PK id) {   this.id = id;   }   }   public class TTrap {  /**    * @param args   */   public static void main(String[] args) {   MyT<Integer> my = new MyT<Integer>();   my.setId(100);    System.out.println(my.getId() + ":" + my.getId());   MyT mynew = my;    System.out.println(mynew.getId() + ":" + mynew.getId());   }   }  在mynew.getId()这一句中实际上编译器这时候仅仅将它识别为Number了,直接当做Integer使用会报错,除非强制转型方可当做Integer来使用。这里就相当于将泛型信息擦除了,程序只有到了真正运行时环境下才能把其当做Integer来用,编译期间他不认识其实质面目。Java擦除泛型信息是将该对象所有的泛型信息全部擦除掉,不仅仅是那个传入的泛型,如果此类本身也定义了其他泛型相关的方法、变量,统统没有了!  class MyTT<PK extends Number> {   private PK id;    private List<String> list;   public PK getId() {   return id;   }    public void setId(PK id) {   this.id = id;   }    public List<String> findRows() {   list = new ArrayList<String>();   list.add("步惊云");     list.add("聂风");   5 / 14      return list;   }   }   public static void main(String[] args) {    MyTT<BigInteger> myTT = new MyTT<BigInteger>();   for (String str : myTT.findRows()) {    System.out.println(str);    }       MyTT my2 = myTT;    List listNoString = my2.findRows();     }  执行MyTT my2 = myTT;实际上是擦除了泛型的所有信息,就连之前定义的public List<String> findRows()也被无辜的擦除了泛型信息。编译时只能认识findRows方法返回的是List而不是List<String>。 10. 遇到含有.的字符串分割成字符串数组   public static void main(String[] args) {   String str = "www.google.cn";   String[] array = str.split("\\.");   System.out.println(array.length);    }  直接用String[] array = str.split(".");不起作用,因为”.”代表可以匹配任意字符,必须转义。 11. 什么样的对象存在线程安全问题  当我们刚学Java的时候不会考虑多线程的问题,在自己的IDE环境下运行成功了就行了,不会考虑并发使用此程序的时候会出现什么情况。等做程序员一段时间后发现自己编写的程序确实存在,多线程安全问题。之后走火入魔似地给自己写的方法加上synchronized。其实我们有时候没搞懂什么情况下会出现线程安全的问题。如果我们开发的是单机版的C/S应用系统,客户的计算机就是软件产品的服务器,那么会不会有并发现象呢?只要不是恶意恶搞你的软件,一般一个客户就对应着一个服务,这个时候不存在并发访问的问题,所以一般情况下不会考虑多线程的问题。如果在基于B/S的Web系统中,可能服务器是一台机器,世界各地的客户都来访问你开发的系统,为这些世界各地的客户提供服务,这个时候可能会出现线程安全的问题。为什么说可能,而不是一定呢?如果你的所有的类和类之间的调用都是通过new一个新的对象为之服务(极端情况下还真有),那么new实际上是在服务器内存中新开辟一块内存空间承载对象,那么这种极端情况是不存在线程安全问题的,只要您的服务器内存极大——1TB内存,每日客户量在2万人左右,估计运行1个月应该差不多没什么问题。不过考虑成本,一般没这样高级的服务器让这种极端的程序运行吧。那么最多的就是类之间的调用不是永远的new一个新的出来,而是为了节省资源,使用对象缓存池或者干脆整个应用软件调用比较频繁的类就使用一个单例对象就得了,每次使用这个对象都是原来已有的,不必在内存新建一个,这样垃圾回收器的工作量也不会那么大。而恰恰是这个时候,这个复用的
分享到:
评论

相关推荐

    个人总结的java常识

    个人总结的java常识

    JAVA 常识 DOC版

    • • java词义 • • Java简介 • • Java语言 • • 相关技术 • • Java开源项目 • • 历史发展及特点 • • Java版本历史 • • Java与Internet • • Java的八大基本数据类型及其包装类 • java面向...

    0854考研复试 综合面试速成(1):C/C++/Java常识 Akira37.pdf

    0854考研复试综合面试速成笔记——C/C++/Java常识。

    Java常识

    介绍了Java的基本常识和用法

    Java并发编程常识

    Java并发编程常识 Java并发编程常识 Java并发编程常识

    java基础知识电子书

    一本比较好的JAVA基础知识电子书,比较容易看懂,需要安装adobe reader 8才能看,可以去天空www.skycn.com下载个。

    autocode中文java版

    符合J2EE的MVC开发模式结合工厂模式,代码通俗易懂,只要稍微有点java常识的人就可以使用本软件来开发大型的java项目,本工作室的开发团队汲取多位资深开发人员多年的项目开发经验开发出本软件,目前使用本软件的...

    AutoCode代码生成器(JAVA版)

    符合J2EE的MVC开发模式结合工厂模式,代码通俗易懂,只要稍微有点java常识的人就可以使用本软件来开发大型的java项目,本工作室的开发团队汲取多位资深开发人员多年的项目开发经验开发出本软件,目前使用本软件的...

    JAVA新手须知的常识

    内有学习别人介绍学习JAVA的经验及新手常犯的错误

    Java并发编程常识-梁飞.rar

    Java并发编程常识.ppt,阿里大牛梁飞编写,非常实用,欢迎大家想学习

    Java小常识

    Java小常识

    java社会公共常识科普网的设计与实现毕业设计程序

    采用java技术构建的一个管理系统。整个开发过程首先对系统进行需求分析,得出系统的主要功能。接着对系统进行总体设计和详细设计。总体设计主要包括系统功能设计、系统总体结构设计、系统数据结构设计和系统安全设计...

    Java编程基础常识.pdf

    Java编程基础常识.pdf

    JAVA开发常识.pdf

    JAVA开发常识.pdf

    JAVA相关基础知识

    JAVA相关基础知识,基本的java常识,供刚学java的朋友看下

    java基础常识与概念

    基础概念与常识 Java 语言有哪些特点? JVM vs JDK vs JRE JVM JDK 和 JRE 什么是字节码?采用字节码的好处是什么? 为什么说 Java 语言“编译与解释并存”? Oracle JDK vs OpenJDK Java 和 C++ 的区别? 基本语法 字符...

Global site tag (gtag.js) - Google Analytics