`
article2008
  • 浏览: 71727 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

JAVA中String类以及对象池的概念

阅读更多

学java的都知道String这个类,是我们一般都要用的一个类,那么我们对这个类又了解多少呢?
下面我来给大家介绍下这个类!
String 这个类有两大模式一个是对象池的概念,而另一个就是不变模式!
String类和对象池
   我们知道得到String对象有两种办法: String str1="hello"; String str2=new String("hello"); 这两种创建String对象的方法有什么差异吗?当然有差异,差异就在于第一种方法在对象池中拿对象,第二种方法直接生成新的对象。在JDK5.0里面, Java虚拟机在启动的时候会实例化9个对象池,这9个对象池分别用来存储8种基本类型的包装类对象和String对象。当我们在程序中直接用双引号括起 来一个字符串时,JVM就到String的对象池里面去找看是否有一个值相同的对象,如果有,就拿现成的对象,如果没有就在对象池里面创建一个对象,并返 回。所以我们发现下面的代码输出true: String str1="hello"; String str2="hello"; System.out.println(str1==str2); 这说明str1和str2指向同一个对象,因为它们都是在对象池中拿到的,而下面的代码输出为false: String str3="hello" String str4=new String("hello"); System.out.println(str3==str4); 因为在任何情况下,只要你去new一个String对象那都是创建了新的对象。与此类似的,在JDK5.0里面8种基本类型的包装类也有这样的差异: Integer i1=5;//在对象池中拿 Integer i2 =5;//所以i1==i2 Integer i3=new Integer(5);//重新创建新对象,所以i2!=i3 对象池的存在是为了避免频繁的创建和销毁对象而影响系统性能,那我们自己写的类是否也可以使用对象池呢?当然可以,考察以下代码: import java.util.*;

public class Student {
        private String name;

        private int age;

        private static HashSet<Student> pool = new HashSet<Student>();
// 对象池

        public Student(String name, int age) {
                this.name = name;
                this.age = age;
        }
        // 使用对象池来得到对象的方法
        public static Student newInstance(String name, int age) {
// 循环遍历对象池
                for (Student stu : pool) {
                        if (stu.name.equals(name) && stu.age == age) {
                                return stu;
                        }
                }
                // 如果找不到值相同的Student对象,则创建一个Student对象
                //并把它加到对象池中然后返回该对象。
                Student stu = new Student(name, age);
                pool.add(stu);
                return stu;
        }
}

class Test {
        public static void main(String[] args) {
                Student stu1 = Student.newInstance("tangliang", 30);
// 对象池中拿
                Student stu2 = Student.newInstance("tangliang", 30);
// 所以stu1==stu2
                Student stu3 = new Student("tangliang", 30);
// 重新创建,所以stu1!=stu3
                System.out.println(stu1 == stu2);
                System.out.println(stu1 == stu3);
        }
}

6, 2.0-1.1==0.9吗? 考察下面的代码: double a=2.0,b=1.1,c=0.9; if(a-b==c){ System.out.println("YES!"); }else{ System.out.println("NO!"); } 以上代码输出的结果是多少呢?你认为是“YES!”吗?那么,很遗憾的告诉你,不对,Java语言再一次cheat了你,以上代码会输出“NO!”。为什 么会这样呢?其实这是由实型数据的存储方式决定的。我们知道实型数据在内存空间中是近似存储的,所以2.0-1.1的结果不是0.9,而是 0.88888888889。所以在做实型数据是否相等的判断时要非常的谨慎。一般来说,我们不建议在代码中直接判断两个实型数据是否相等,如果一定要比 较是否相等的话我们也采用以下方式来判断: if(Math.abs(a-b)<1e-5){ //相等 }else{ //不相等 } 上面的代码判断a与b之差的绝对值是否小于一个足够小的数字,如果是,则认为a与b相等,否则,不相等。

7,判断奇数 以下的方法判断某个整数是否是奇数,考察是否正确: public boolean isOdd(int n){ return (n%2==1); } 很多人认为上面的代码没问题,但实际上这段代码隐藏着一个非常大的BUG,当n的值是正整数时,以上的代码能够得到正确结果,但当n的值是负整数时,以上 方法不能做出正确判断。例如,当n=-3时,以上方法返回false。因为根据Java语言规范的定义,Java语言里的求余运算符(%)得到的结果与运 算符左边的值符号相同,所以,-3%2的结果是-1,而不是1。那么上面的方法正确的写法应该是: public boolean isOdd(int n){ return (n%2!=0); }
8,拓宽数值类型会造成精度丢失吗? Java语言的8种基本数据类型中7种都可以看作是数值类型,我们知道对于数值类型的转换有一个规律:从窄范围转化成宽范围能够自动类型转换,反之则必须 强制转换。请看下图: byte-->short-->int-->long-->float-->double char-->int 我们把顺箭头方向的转化叫做拓宽类型,逆箭头方向的转化叫做窄化类型。一般我们认为因为顺箭头方向的转化不会有数据和精度的丢失,所以Java语言允许自 动转化,而逆箭头方向的转化可能会造成数据和精度的丢失,所以Java语言要求程序员在程序中明确这种转化,也就是强制转换。那么拓宽类型就一定不会造成 数据和精度丢失吗?请看下面代码: int i=2000000000; int num=0; for(float f=i;f< 哈哈,你快要不相信你的眼睛了,结果竟然是true;难道f1和f2是相等的吗?是的,就是这样,这也就能解释为什么上一段代码输出的结果是0,而不是 50了。那为什么会这样呢?关键原因在于你将int值自动提升为float时发生了数据精度的丢失,i的初始值是2000000000,这个值非常接近 Integer.MAX_VALUE,因此需要用31位来精确表示,而float只能提供24位数据的精度(另外8位是存储位权,见IEEE745浮点数 存储规则)。所以在这种自动转化的过程中,系统会将31位数据的前24位保留下来,而舍弃掉最右边的7位,所以不管是2000000000还是 2000000050,舍弃掉最右边7位后得到的值是一样的。这就是为什么f1="=f2的原因了。" System.out.println(f1="=f2);" f2="i+50;" float f1="i;" i="2000000000;" int ,那么请运行一下,结果会让你大吃一惊!没错,输出结果是0,难道这个循环根本就没有执行哪怕一次?确实如此,如果你还不死心,我带你你看一个更诧异的现 象,运行以下代码,看输出什么? 如果你回答50 请考察以上代码输出多少? System.out.println(num); } num++;>


9,i=i+1和i+=1完全等价吗?
    可能有很多程序员认为i+=1只是i=i+1 的简写方式,其实不然,它们一个使用简单赋值运算,一个使用复合赋值运算,而简单赋值运算和复合赋值运算的最大差别就在于:复合赋值运算符会自动地将运算 结果转型为其左操作数的类型。看看以下的两种写法,你就知道它们的差别在哪儿了:
  (1) byte i=5;
      i+=1;
  (2) byte i=5;
      i=i+1;
     第一种写法编译没问题,而第二种写法却编译通不过。原因就在于,当使用复合赋值运算符进行操作时,即使右边算出的结果是int类型,系统也会将其值转化为 左边的byte类型,而使用简单赋值运算时没有这样的优待,系统会认为将i+1的值赋给i是将int类型赋给byte,所以要求强制转换。理解了这一点 后,我们再来看一个例子:
  byte b=120;
  b+=20;
  System.out.println("b="+b);
   说到这里你应该明白了,上例中输出b的值不是140,而是-116。因为120+20的值已经超出了一个byte表示的范围,而当我们使用复合赋值运算时 系统会自动作类型的转化,将140强转成byte,所以得到是-116。由此可见,在使用复合赋值运算符时还得小心,因为这种类型转换是在不知不觉中进行 的,所以得到的结果就有可能和你的预想不一样。

对于J2ME的答案也是1一个 在J2ME里面没有对象池的概念。

在JDK中有jdk里面有9个对象池,8个基本类包装类对象和String类对象。

不变模式

什么是不变模式呢?
String s = "xx";
String s = "aa";
不变模式就是 一个字符串对象 创建后它的值就不能再被改变。
每 改变一次就产生一个垃圾,它只是一个对象的引用地址,指向一个值,如果把他的值换了,那么只是换了一个对象的引用地址,至始至终没有改变它本身的值,如果 要在系统中频繁的使用字符串引用,那么建议使用StringBuffer,先放到缓冲区里,然后直接全部写入。先暂时写到这里把!

分享到:
评论

相关推荐

    Java中的String池

    当我们使用`new String("Hello")`创建字符串时,即使字符串字面量已经存在于常量池中,也会创建一个新的String对象。这是因为`new`关键字总是创建一个新的对象实例。 #### 示例代码解析 考虑下面这段示例代码: `...

    java自制string类例程

    在Java编程语言中,String类是一个非常基础且重要的部分,它是不可变的,也就是说一旦创建了一个String对象,就不能更改它的内容。然而,许多初学者在学习过程中可能会尝试自己创建一个类似的字符串类,以便更好地...

    java中String类的知识

    **创建String对象的方式:** 1. **直接赋值法:** ```java String str1 = "otherwords"; ``` 这种方式创建的字符串会直接放在常量池中,如果第二次出现相同的字符串,那么它会直接指向常量池中的已有对象。 2....

    java String类的实现

    Java中的`String`类是编程中最常用的类之一,它在Java的`java.lang`包中,无需显式导入即可使用。`String`类代表不可变的字符序列,这意味着一旦创建了`String`对象,它的值就不能改变。这个特性使得`String`在处理...

    java中Object对象String对象的解析.pdf

    Java 中的 Object 对象和 String 对象是两个非常重要的概念。在 Java 中,每个对象都继承自 Object 对象,这意味着每个对象都拥有 Object 对象的方法和属性。String 对象是 Java 中最常用的对象之一,它用于存储字符...

    深入了解java 中的String

    深入了解Java中的String类是至关重要的,因为String在Java编程中占据着极其重要的位置。下面将对给定的信息进行深入分析: ### 1. String 类是 final 的,不可被继承 在Java中,`String` 类被声明为 `final` 类型...

    JAVA类与对象及数组习题

    JAVA类和对象及数组是JAVA编程语言的基础概念。下面是关于JAVA类和对象及数组的习题,涵盖了构造方法、继承、多重继承、变量声明、数组初始化等方面的知识点。 1. 构造方法的调用方式: 构造方法是类的特殊方法,...

    String类创建对象问题

    在 Java 中,`String` 类并不属于八种基本数据类型之一,而是作为一个对象存在。这意味着 `String` 对象默认值为 `null`。尽管如此,`String` 类拥有其独特之处,比如它是不可变的(final),这保证了字符串一旦创建便...

    java类与对象实例

    "java类与对象实例" 在 Java 中,类和对象是两个紧密...理解 Java 语言的类和对象概念对于编写高效、可维护的 Java 程序非常重要。这些概念是学习 Java 语言的基础,理解这些概念可以帮助开发者更好地编写 Java 程序。

    小心String的陷阱——深入剖析Java中String的处理机制

    `String Pool`是存储`String`字面量的缓存池,当通过字面量的方式创建`String`对象时,Java虚拟机首先检查`String Pool`中是否已经存在相同的字符串,如果存在,则返回该字符串的引用,而不是创建一个新的对象。...

    解析Java中的String对象的数据类型 字符串

    在Java中,如果我们使用字面值方式创建的String对象,它们是常量池中的字符串常量,如果我们使用new关键字创建的String对象,它们是运行时创建的新对象。例如,String s0="kvill";,String s1=new String("kvill");...

    java编程中的类和对象的详细介绍

    Java编程中的类和对象是面向对象编程的核心概念。面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它基于“对象”的概念,强调数据和操作数据的方法结合在一起,提供更好的代码组织和可维护性。 ...

    我们一起学Java之String

    这一特性对于Java内存管理有着重要影响,因为String对象会存储在方法区的字符串常量池中,以避免重复创建相同的字符串,从而提高内存使用效率。 在JDK 8版本中,字符串常量池的位置发生了变化,从方法区移至Java堆...

    JAVA面试题解惑系列(二)——到底创建了几个String对象-JAVA程序员JAVA工程师面试必看.pdf,这是一份不错的文件

    本文将深入探讨 JAVA 中 String 对象的创建机制,解答常见的面试题目,并探索 String 对象池的概念和机制。 一、String 对象的创建方式 在 JAVA 中,String 对象可以通过多种方式创建,包括使用 new 关键字、使用...

    java中String类型和int类型比较及相互转换

    本文将深入探讨Java中String类型和int类型之间的比较方法以及相互转换的技术,这对于理解和优化代码逻辑、提升程序性能具有重要意义。 ### 一、String类型与int类型的基本概念 #### 1.1 String类型 String类型在...

    Java中String判断值为null或空及地址是否相等的问题

    本文主要讨论了如何正确判断Java中的String对象是否为null、空值("")以及它们的地址是否相等。在处理字符串时,了解这些概念对于避免程序出错至关重要。 首先,我们需要区分`null`和空字符串`""`。`null`表示变量...

    一文带你吃透Java中的String类.rar

    本文将深入探讨String类的特性、构造、方法以及在内存中的表现,帮助你全面理解这个核心类。 首先,String类在Java中是不可变的。这意味着一旦创建了一个String对象,它的值就不能被改变。这是由其内部实现决定的,...

    Java中的String对象是不可变的吗Java开发Jav

    在Java编程语言中,String对象被认为是不可变的。这个特性是Java设计者为了优化性能、安全性和线程安全性而有意设定的。理解String对象的不可变性对于Java开发者来说至关重要,因为它影响着代码的编写、内存管理和多...

Global site tag (gtag.js) - Google Analytics