- 浏览: 979499 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
Mr.Cheney:
去掉 UUID字符串中的“-” 直接replaceAll(&q ...
JAVA生成全局唯一ID 使用 java.util.UUID -
呜哩喵:
楼主nice
java中的时间操作 -
zxs6587:
Thinking inJava我读着好像说要建立基类对象啊!请 ...
创建子类的对象时也要创建其所有父类的对象? -
just_Word:
getFullYear
date.getyear -
JamesQian:
我觉得楼上的synchronized(this),notify ...
notify() wait()
学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,先放到缓冲区里,然后直接全部写入。先暂时写到这里把!
下面我来给大家介绍下这个类!
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,先放到缓冲区里,然后直接全部写入。先暂时写到这里把!
发表评论
-
关于数组和List之间相互转换的方法
2011-04-14 21:04 13831.List转换成为数组。( ... -
java的几种对象(PO,VO,DAO,BO,POJO)解释
2011-03-24 10:13 1344java的几种对象(PO,VO,DAO,BO,POJO)解释 ... -
switch
2010-12-02 19:02 11451 public class Switch { 2 ... -
优化的冒泡排序
2010-09-25 14:18 1369public static void bubble_Sort( ... -
java变量命名规则
2010-08-13 23:15 23711. 大小写有别,例如 a 和 A是两个变量 2. 长度任意 ... -
String.getBytes()的问题
2010-08-13 22:46 1649转载 http://java.chinaitlab.c ... -
tomcat 修改端口
2010-08-09 22:41 2006Tomcat端口修改: 在Tomcat安装目录下的conf目 ... -
tomcat 中增加用户名和密码
2010-08-09 22:41 1916原来的tomcat-user.xml是 <?xml ... -
Eclipse is running in a JRE, but a JDK is required
2010-07-28 09:30 15301 安装了maven插件,使用的时候老是有这样的提示: 08- ... -
安装Eclipse的maven插件
2010-07-27 11:01 1825Installing m2eclipse Core To i ... -
Attach Library Sources and Javadocs
2010-07-26 13:41 1926Attach Library Sources and Java ... -
maven 安装jaxb插件
2010-07-18 15:10 65691. Put your schemas ( ... -
java接受控制台输入
2010-07-16 13:45 2713import java.io.*; public c ... -
将xsd文件转化为java类
2010-07-10 15:31 2513最近有一个需求是把xsd文件中定义的数据类型转化为java类 ... -
jconsole attache sun glassfish
2010-06-13 17:04 1353To Set Up JConsole Connectivity ... -
suse下lamp的安装
2010-05-31 16:45 1565首先卸载suse缺省安装的apache2 主要是在网上看到人家 ... -
java的property配置文件的用法
2010-05-30 15:04 1143在我们平时写程序的时候,有些参数是经常改变的,而这种改变不是我 ... -
让ubuntu下的eclipse支持GBK编码
2010-05-30 14:38 1520今天,把windows下的工程导入到了Linux下eclips ... -
java路径中/的问题
2010-05-18 17:23 1367windows支持两种文件分隔符“/”和“\” 且使用“/”时 ... -
java中serializable是可以继承的
2010-05-16 21:58 5508import java.io.FileInputStream; ...
相关推荐
Java字符串池和字符对象是Java编程中的重要概念,主要涉及到String类的特性和内存管理。在Java中,String是一个不可变类,这意味着一旦创建了一个String对象,它的值就不能被修改。这种不变性使得String对象在多线程...
通过运行和调试这些代码,你可以加深对Java字符串、正则表达式以及日期时间格式化的理解。 总之,理解和熟练掌握Java中的字符串操作、正则表达式以及日期时间格式化对于任何Java开发者来说都是必不可少的技能。通过...
总结,Java对象转换为JSON字符串或字符串数组是通过引入JSON库,如`json-lib`,然后利用其提供的序列化和反序列化方法实现的。了解并熟练掌握这些方法对于进行Java和JSON之间的数据交换至关重要。在实际项目中,根据...
首先,我们要明白Java中的字符串是`String`类的对象,它提供了丰富的API用于字符串的处理。例如,我们可以使用`substring()`方法来截取字符串的一部分,但这并不适用于提取括号内的内容,因为我们需要识别开括号和闭...
字符串的`intern()`方法会将字符串对象加入到字符串池中,如果字符串池中已有相同的字符串,则返回池中的引用。 10. **编码与解码**: 字符串与字节之间的转换涉及到编码问题,如`getBytes()`和`new String(byte...
在Java编程语言中,字符串...以上只是Java字符串操作的一小部分,实际开发中还有许多其他方法和特性,如国际化(I18N)、正则表达式等,都需要程序员灵活掌握。理解并熟练运用这些操作,能有效提高代码质量和效率。
使用Java操作JSON字符串对象,使用Java操作JSON字符串对象
在Java编程中,经常需要将日期对象转化为字符串形式以便于存储或显示,或者反过来将字符串转化成日期对象来进行日期计算等操作。本文将详细介绍如何在Java中实现这两种转换。 #### 一、将一个Date类型的变量转换为...
Java 字符串转换为日期和时间比较大小 Java 字符串转换为日期和时间比较大小是 Java 开发中常见的操作。下面我们将详细介绍两种方法来实现 Java 字符串转换为日期和时间比较大小。 方法一:使用 SimpleDateFormat ...
在Java中,字符串是不可变的对象,由`String`类表示。这意味着一旦创建了一个字符串对象,它的内容就不能被修改。因此,如果我们要对一个字符串中的字符进行排序,我们不能直接改变原字符串,而是需要创建一个新的...
### Java字符串查找和提取异常处理 #### 概述 本文将详细介绍如何在Java中实现字符串查找与提取功能,并在此过程中妥善处理可能出现的各种异常情况。通过分析提供的代码示例`IndexOfAndCharAt.java`,我们将了解到...
通过以上公式和示例表格,我们可以更直观地理解Java字符串的内存占用情况。需要注意的是,这只是一个近似的计算方法,实际内存占用会受到JVM实现细节的影响。 总之,在Java中计算字符串所占用的内存是一项复杂的...
### Java字符串长度不够前面或后面补0 在Java编程中,有时我们需要确保字符串达到特定的长度,如果实际长度不足,则需要在字符串的前部或后部添加特定字符(如0)来填充,使得最终字符串满足预设长度的要求。本文将...
在Java编程语言中,将字符串转换为16进制ASCII值是一个常见的操作,尤其是在处理数据编码、网络通信或存储时。这个过程涉及到字符到数字的...理解这些概念和方法,对于在Java开发过程中处理字符串编码问题至关重要。
本文将深入探讨“JAVA可逆带秘钥字符串加密算法”,这是一种允许数据在加密后仍能通过正确的密钥解密回原始形式的加密技术。 在Java中,最常见的可逆加密算法包括DES(Data Encryption Standard)、3DES(Triple ...
在Java中,字符串是一系列字符的集合,与其他编程语言将字符串视为字符数组不同,Java采用了更为先进的方式——将字符串视为`String`类型对象来处理。这种设计使得Java能够提供丰富的字符串处理功能,包括但不限于...
在分析和解决Java字符串实验题目时,我们需要综合运用上述知识,例如查找子串、替换字符、分割字符串、处理异常情况等。理解并熟练掌握这些基本概念和方法,对于提升Java编程能力至关重要。 总之,Java中的字符串...
以下是一些Java `String`类中常用的方法,这些方法对于理解和操作字符串至关重要。 1. **创建字符串** - `new String()`: 使用此构造函数创建一个新的字符串对象,可以传入字符数组或另一个字符串作为参数。 - `...
Java反射机制是Java语言提供的一种强大功能,它允许运行中的Java程序对自身进行...通过结合XML序列化和解析,我们可以方便地在Java对象和XML数据之间进行转换,这对于数据交换、持久化存储或者网络通信都有很大的帮助。