Java笔记10——认识String类

目录

JKD中String类的声明

创建字符串的四种方式

字面量

 2.字符串比较相等

3.关于字符串的常量池问题(重点)

手工入池:String类提供的intern方法。

4.字符串的不可变性

5.如何修改字符串的内容

6. 字符串常见操作

6.1 字符串比较

6.⒉字符和字符串的相互转换。

6.3 字符串替换

6.4 字符串拆分

6.5 字符串截取

6.6 其他操作方法

关于StringBuilder类的具体使用:

面试题:请解释String、StringBuffer、StringBuilder的区别

小结


String类的所有针对字符串的操作方法都不会修改原字符串,而是产生了一个新的字符串!! ! ! ! ! ! 

字符串的不可变性!! !
这一点一定要牢记,牢记这点去看问题。

JKD中String类的声明

发现它继承了多个接口,其中Comparable接口就是我们上次刚学的。

为何String类被final修饰?

被final修饰的类无法被继承,String类不存在子类。
这样的话就可以保证所有使用JDK的人,大家用到的String类仅此一个,大家都相同。.

那么大家都随意的拓展自己的子类,你的String代码在你自己拓展的子类里面可以跑起来,在别人没有覆写该子类的话就跑步起来。大家都是自己的方法和想法,得不到统一,那还怎么写代码,总要有个规矩。

灵活不一定是好事,灵活就代表着不确定性,不确定就表示不稳定,如果代码都是不确定的,那可不行,所以需要final修饰。

继承和方法覆写在带来灵活性的同时,也会带来很多子类行为不一致导致的问题。

什么时候会用到final修饰类

你的这个类不希望有别的版本,到此为止。
所有使用者用的这个类完全相同,没有别的实现。

创建字符串的四种方式

// 方式一 直接赋值
String str = "Hello Bit";



// 方式二 通过构造方法产生对象(String也是一个类)
String str2 = new String("Hello Bit");



// 方式三  通过字符数组产生对象
char[] array = {'a', 'b', 'c'};
String str3 = new String(array);



//方式四:通过String的静态方法valueOf(任意数据类型)=>转为字符串
  String str4 = String.valueOf(10);

 最常用的是 方式一和方式四

在官方文档上 (Overview (Java Platform SE 8 ) (oracle.com)) 我们可以看到 String 还支持很多其他的构 造方式, 我们用到的时候去查就可以了. 

字面量

String引用数据类型。


 后面这个“hello world”也是字符串的对象,那么为什么没有new?因为JDK对String做了优化。

在内存中的分布:

 如果此时再创建一个String对象,里面的内容一致。

String str2 = "hello world";

 现在来比较他们的地址用 ==

 true,表示地址相等。当然可能你会说这是因为内容一致才是true的,现在换个表示方法

 equals方法是区分大小写的,如果你想不区分大小写的比较,也是有方法的。

  

当字符串对象的内容一模一样时,并不会开辟新的空间,而是去指向相同的空间。

这一步在内存中是怎么变化的? 

注释:把图中的str2想像成str3即可,写错了。

 不过是在栈区又开辟了一个局部变量,来保存这个堆区中String对象地址。

问题来了!现在修改原理的str1的内容,然后打印每个str会是什么结果?

 运行结果:

为什么会是这样的结果?

关键在于这一步:

 

"abc”也是字符串的字面量,是一个新的字符串对象,str1实际上指向了新的字符串象"abc"

 str3任指向原字符串对象"hello world"

 2.字符串比较相等

所有引用数据类型在比较是否相等时,一定要使用equals方法比较。
JDK常用类,都已经覆写了equals方法,大家直接使用即可。(学会用现成的工具)

如:String,Integer。

强调:引用数据类型使用“=="比较的仍然是数值(地址是否相等)

还有一种场景,小知识。如果String这个变量由用户从浏览器输入,下面两种方法更合理!

 判断用户输入的是否为字符串张三,那种方式更好。

第二中方法更好,以后牵扯到用户输入就—定要做判空处理。万一这个用户在使用的时候忘记输出了这个内容呢?那第一种比较岂不是空指针引用了,肯定会报错的。


空指针异常了!  现在把第一种方法注释了。

 这样就不会报错了。

要比较的特定内容本身就是字符串的字面量,一定不是空对象,把要比较的内容放在equals的前面。就可以方便处理userName为空的问题。

3.关于字符串的常量池问题(重点)

什么是字符串的常量池?

当使用直接赋值法产生字符串对象时,JVM会维护一个字符串的常量池,若该对象在堆中还不存在,则产生一个新的字符串对象加入字符串的常量池中。
 

当继续使用直接赋值法产生字符串对象时,JVM发现该引用指向的内容在常量池中已经存在了,则此时不再新建字符串对象,而是复用已有对象。

注释:在JDK8之前 常量池 在方法区中开辟,在8之后就把 常量池 挪到了堆区中

重新回顾下这一步在内存中的开辟顺序 

 第一步str1,因为不存在“hello world”,所以产生了一个新对象。

第二步str2,因为发现常量池中已经存在了一模一样的对象,所以不在产生新的对象,复用已有对象,直接指向这个一样对象的地址。

第三步依旧如初。 所以这三步就只产生了一个对象。        

 那么现在这三个语句在内存执行中会有怎么样的不同呢?

 1. 因为是通过构造方法产生的对象,所以str1.2.3跟上面第一种情况不一样,各各都是不同的地址。

测试一下:果然地址不相同。

 现在开始分析:程序都是从右向左执行的。

先是碰到“hello world”,因为此时的常量池不存在这个对象,所以先在字符串常量池中开辟一个“hello world”空间。

然后碰到 new,要知道,有new就会有新空间,所以又在常量池外面,却还是在堆区中开辟一块内容为 “hello world” 的空间,暂时给这块空间地址取名为h1

最后是在栈区中开辟一块空间名为 str1,里面保存的就是h1空间地址。

注释:有new了之后,就不是直接指向常量池了。

--------至此为止第一行执行结束

第二行也是先遇到“hello world”,发现现在的常量池中已经存在了一个一模一样的了,就不会再次在常量池中开辟空间了,然后碰到new,在常量池外,堆区内开辟一个也是内容为 “hello world”的空间,暂时给这块空间地址取名为h2,最后在栈区中的str2保存的是h2的地址。

第三步操作跟第二步一样。

大概原理图:

注释: 有new就有新空间,这三行代码产生四个字符串对象,其中一个在常量池中,其余三个在堆中.

浅浅的小知识,随便看看。

 一个JVM进程中,所有常量都是共享的。

手工入池:String类提供的intern方法。

 调用intern方法会将当前字符串引用指向的对象保存到字符串常量池中。

a.若当前常量池中已经存在了该对象,则不再产生新的对象,返回常量池中的String对象
 

b.若当前常量池中不存在该对象,则将该对象入池,返回入池后的地址。

思考题:根据上面两条规则,问下面这几条代码的运行结果是什么?

 解析:

程序从右向左执行,第一天语句跟之前说的一样,没区别

 关键是第二句:str1.intern(); 这语句先是问你常量池中有没有str1里面保存的 hello对象?

发现常量池中已经有了,所以执行 a分支,不再产生新的对象,返回常量池中的字符串对象地址,但我们此时没有用变量来接收啊,所以说str1还是指向常量池外面的那块空间,没动过。

第三句,因为常量池有中间存在了heoll所以直接复用,让str2指向了这个对象的地址。

这就是最后呈现出来的样子

 答案肯定是:false

怎么让答案变成 true呢?让str1接收intern方法的返回值就行了

内存图更新: 

现在用字符数组 创建字 符串

这执行的结果还会是什么? 

 

 解析:第一条语句就是new一个字符数组,有new就有新空间,新空间肯定是在堆区上的。

注释:这个abc此时还是字符数组,常量池中还没有它的存在。 

"abc",这个本身就算一个对象了,在常量池中存放着,之前构造方法只是开辟了新空间,并没有把这个字符串放在常量池中这一步骤,做到这一步的要是因为它本身 " " 就是个对象,自己就已经完成了这一步。

 所以现在看第二个语句:

 构造方法里面现在放着的是一个字符数组,而不是字符串了,所以并没有往常量池中放东西,只是普通的有new就有新空间。

此时常量池还是空着的,第二个只做了开辟一块空间,里面保存字符串“abc”,然后str1变量指向它就没了。 

第三语句 str1.intern(); 现在此时由于常量池中没有字符串“abc”的存在,所以执行的是分支二。

若当前常量池中不存在该对象,则将该对象入池,返回入池后的地址。

它就会把原本在常量池外,堆内,str1执行的空间搬移到常量池中。

注释:str1还是一直执行本来的那块空间,只是现在这块空间的位置变到了常量池中。

现在看第四句: 是直接赋值的形式,现在常量池中已经存在了abc这个字符串,所以进行复用,同样执行这块空间地址。

 所以,最终比较地址的答案:true

4.字符串的不可变性
 

所谓的字符串不可变指的是字符串对象的内容不能变,而不是字符串引用不能变。

可能会有很多疑惑,不是说字符串内容不可变吗?我怎么觉得想改变就跟改变啊!

 这里的不可变指的 "hello"   "world"   "helloworld"  "!!!"
"helloworld!!!"这些字符串对象一旦声明后就无法修改其内容。他们都是一个个单独的个体!

内存图:

因为都是直接赋值,所以在直接在常量池中创建对象。

第一句执行后

 第二句:str += "wolrd ";从右向左执行,先是在常量池中创建这个对象“wolrd”,然后是 += 这是拼接,拼接后的会形成一个新的字符串对象,在常量池中生成。让str重新指向这个对象的地址。

 第三局语句也是同样的道理。

所以我们所说的不可变性指的是这个字符串对象一旦产生赋值后,这个内容里面就无法被修改了。而不是指 str 这个引用指向的对象不可变。引用指向谁是可以随意改变的,但字符串对象不可变。

我们的拼接是完全实实在在生成了新的字符串在常量池在,原来要求的字符串对象根本没有对它进行任何的更改,依旧保留着。

为何字符串的对象无法修改内容而其他类的对象能修改内容。
 

字符串其实就是一个字符数组   ——》 char[ ],字符串保存的值实际上在数组中保存。

看看源代码的内容:

这是1.7的JDK 新的

 这是JDK8的 以前的

以前是char数组,现在改成了byte数组 ,知道就行。

我们产生一个字符串对象的时候,它保存的这个内容、数值,实际上最终都在value这个数组都保存了。发现这个value这个字节数组是被private封装起来了。String外部无法访问这个value数组。而且String类里面也没有写get和set的方法。所以对外部而言根本不可见,无法使用和访问。

因此字符串对象的内容无法修改->String类的外部根本拿不到这个value数组

举例: str直接赋值的方法写一个 hello 字符串

 在常量池 "hello"这个字符串内部其实有个数组 value,之所以长成 hello,是因为这个数组是hello,为啥改变不了,因为这个value是私有权限,String也并没有提供get和set方法。

5.如何修改字符串的内容

a.在运行时通过反射破坏value数组的封装(了解,不推荐,反射是所有框架的基础)
 


b.更换使用StringBuilder或者StringBuffer类——已经不是一个类了

a.在运行时通过反射破坏value数组的封装:

用a方法的案例代码:

import java.lang.reflect.Field;

public class StringChange {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
//        String str = "hello ";
//        str += "wolrd ";
//        str += "!!!";
//        System.out.println(str);

        String str = "hello";
        System.out.println(str);
        Class<String> cls = String.class;
        // 获取这个属性
        Field field = cls.getDeclaredField("value");
        // 破坏封装,破坏private
        field.setAccessible(true);
        // 在String类的外部通过反射拿到value数组
        char[] value = (char[]) field.get(str);
        value[0] = 'H';
        System.out.println(str);
    }
}

运行结果:被改变了。 

b.更换使用StringBuilder或者StringBuffer类:

若需要频繁进行字符串的拼接,使用StringBuilder类的append方法

StringBuilder类可以修改对象的内容。

 注释:此时的字符串对象跟之前不一样,从始至终都只是一个对象。在一个对象的基础上做更改。

StringBuffer使用方法和StringBuilder完全—样,线程安全,性能较差。

在单线程的情况下一般使用StringBuilder

String,StringBuilder,StringBuffer之间的区别:

 

6. 字符串常见操作

6.1 字符串比较

上面使用过String类提供的equals()方法,该方法本身是可以进行区分大小写的相等判断。除了这个方法之外,String 类还提供有如下的比较操作:

NO方法名称类型描述
1
public boolean equals(Object anObject)
普通区分大小写的比较
2
public boolean equalsIgnoreCase(String anotherString)
普通不区分大小写的比较        
3
public  int compareTo(String anotherString)
普通比较两个字符串的大小

代码示例: 不区分大小写比较

String str1 = "hello" ; 
String str2 = "Hello" ; 
System.out.println(str1.equals(str2)); // false 
System.out.println(str1.equalsIgnoreCase(str2)); // true

在String类中compareTo()方法是一个非常重要的方法,该方法返回一个整型,该数据会根据大小关系返回数值:

1. 相等:返回0.

2. 小于:返回内容小于0.

3. 大于:返回内容大于0。

范例:观察compareTo()比较

        String str1 = "abc";
        String str2 = "aBc";
        System.out.println(str1.compareTo(str2));

        System.out.println("A".compareTo("a")); // -32
        System.out.println("a".compareTo("A")); // 32
        System.out.println("A".compareTo("A")); // 0
        System.out.println("AB".compareTo("AC")); // -1
        System.out.println("王".compareTo("李"));//3133

compareTo()是一个可以区分字符串大小关系的方法,是String方法里是一个非常重要的方法。

字符串的compareTo方法按照字符串内部的每个字符进行  unicode 的比较
 

这里有个概念了解一下:按照"字典序"排列字符串,这是什么意思?
就是按照字符串内部的字符的unicode 码大小排序

字符串的比较大小规则, 总结成三个字 "字典序" 相当于判定两个字符串在一本词典的前面还是后面.

先比较第一 个字符的大小(根据 unicode 的值来判定), 如果不分胜负, 就依次比较后面的内容

6.⒉字符和字符串的相互转换。

字符串的内部实际上就是使用字符数组来存储的。


char数组通过构造方法变成字符串。

 注释:这里是不能用toString方法来转字符串的

将字符数组的部分内容转为字符串对象

字符串内部包含一个字符数组,String 可以和 char[] 相互转换.

代码示例: 获取指定位置的字符

String str = "hello" ; 
System.out.println(str.charAt(0)); // 下标从 0 开始
// 执行结果
h 
System.out.println(str.charAt(10)); 
// 执行结果
产生 StringIndexOutOfBoundsException 异常

代码示例: 字符串与字符数组的转换

String str = "helloworld" ; 
// 将字符串变为字符数组
char[] data = str.toCharArray() ; 
for (int i = 0; i < data.length; i++) { 
 System.out.print(data[i]+" "); 
} 
// 字符数组转为字符串
System.out.println(new String(data)); // 全部转换
System.out.println(new String(data,5,5)); // 部分转换

⒉将字符串中的内容转为字符数组String => char[]

 如果此时把data第一个数组内容改成 ‘H’,那么原来的字符串会受影响吗?

 肯定不会的,很明显。这个数组知识做了,产生了一个新的字符数组,将字符串的内容复制过去。

强调:String对象不可变!!!内容改不了! ! !
 

 代码示例: 给定字符串一个字符串, 判断其是否全部由数字所组成

public static void main(String[] args) { 
 String str = "1a23456" ;  
 System.out.println(isNumber(str) ? " 字符串由数字所组成!" : "字符串中有非数字成员!"); 
 } 
 public static boolean isNumber(String str) { 
 char[] data = str.toCharArray() ; 
 for (int i = 0; i < data.length; i++) { 
 if (data[i]<'0' || data[i]>'9') { 
 return false ; 
 } 
 } 
 return true ; 
 } 

编程时的重要思路:

在处理一个逻辑让你返回true或者false
我们的思路就是在循环中找反例,有一个反例直接return false。有时候找返例比正确的要清晰的多。

我们平常常用的一些方法Java里基本都有

比如我们把之前的if判断换成下面这个,一样可以完成功能。


 

这两个类型间的相互转换是非常重要的。字符串转换为字符数组这个点非常重要
咱碰到的字符串处理的大部分问题都需要转为字符数组来一个个处理。

 

字节常用于数据传输以及编码转换的处理之中,String 也能方便的和 byte[] 相互转换

代码示例: 实现字符串与字节数组的转换处理

String str = "helloworld" ; 
// String 转 byte[] 
byte[] data = str.getBytes() ; 
for (int i = 0; i < data.length; i++) { 
 System.out.print(data[i]+" "); 
} 
// byte[] 转 String 
System.out.println(new String(data));

byte 转换为 String

String 转 byte 

 

 四个中国字却转了这么多数字。它是按照当前默认的字符编码转为字节

上面的方法4:按照指定的编码格式转为字节数组。

如果没有指定就按照默认的编码格式进行。 

 将字符串保存到文件中或是通过网络传输都要用到字节数组。

我们在平常打字的时候,都是先Stirng转byte字节码,然后传送到了再用byte转String显示。

4.字符串查找操作

从一个完整的字符串之中可以判断指定内容是否存在,对于查找方法有如下定义:

(该图出自比特资料)

 

代码示例: 字符串查找,最好用最方便的就是contains() 

String str = "helloworld" ; 
System.out.println(str.contains("world")); // true

注释:该判断形式是从JDK1.5之后开始追加的,在JDK1.5以前要想实现与之类似的功能,就必须借助、indexOf()方法完 成。

代码示例: 使用indexOf()方法进行位置查找

String str = "helloworld" ; 
System.out.println(str.indexOf("world")); // 5,w开始的索引
System.out.println(str.indexOf("bit")); // -1,没有查到
if (str.indexOf("hello") != -1) { 
 System.out.println("可以查到指定字符串!"); 
} 

现在基本都是用contains()方法完成。 使用indexOf()需要注意的是,如果内容重复,它只能返回查找的第一个位置

代码示例: 使用indexOf()的注意点

String str = "helloworld" ; 
System.out.println(str.indexOf("l")); // 2 
System.out.println(str.indexOf("l",5)); // 8 
System.out.println(str.lastIndexOf("l")); // 8 

在进行查找的时候往往会判断开头或结尾。

代码示例: 判断开头或结尾

String str = "**@@helloworld!!" ; 
System.out.println(str.startsWith("**")); // true 
System.out.println(str.startsWith("@@",2)); // ture 
System.out.println(str.endsWith("!!")); // true

6.3 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:

代码示例: 字符串的替换处理

String str = "helloworld" ; 
System.out.println(str.replaceAll("l", "_")); 
System.out.println(str.replaceFirst("l", "_")); 

两个的区别:

 注意事项: 由于字符串是不可变对象 , 替换不修改当前字符串, 而是产生一个新的字符串.

6.4 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

可用方法如下:

代码示例: 实现字符串的拆分处理

String str = "hello world hello Java" ; 
String[] result = str.split(" ") ; // 按照空格拆分
for(String s: result) { 
 System.out.println(s); 
} 

代码示例: 字符串的部分拆分

String str = "hello world hello Java" ; 
String[] result = str.split(" ",2) ; 
for(String s: result) { 
 System.out.println(s); 
} 

拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义.

代码示例: 拆分IP地址

String str = "192.168.1.1" ; 
String[] result = str.split("\\.") ; 
for(String s: result) { 
 System.out.println(s); 
} 

 注意事项:

1. 字符"|","*","+"都得加上转义字符,前面加上"\".

2. 而如果是"",那么就得写成"\\".

3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.

代码示例: 多次拆分

String str = "name=zhangsan&age=18" ; 
String[] result = str.split("&") ; 
for (int i = 0; i < result.length; i++) { 
 String[] temp = result[i].split("=") ; 
 System.out.println(temp[0]+" = "+temp[1]); 
} 

 当你发现你按照指定格式,字符串却没有拆成功,说明是 特殊字符,需要转义。

这种代码在以后的开发之中会经常出现 

6.5 字符串截取

从一个完整的字符串之中截取出部分内容。可用方法如下:

代码示例: 观察字符串截取 

String str = "helloworld" ; 
System.out.println(str.substring(5)); 
System.out.println(str.substring(0, 5)); 

注意事项:

1. 索引从0开始

2. 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

6.6 其他操作方法

 代码示例: 观察trim()方法的使用

String str = " hello world " ; 
System.out.println("["+str+"]"); 
System.out.println("["+str.trim()+"]"); 

trim 会去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等).

代码示例: 大小写转换

String str = " hello%$$%@#$%world 哈哈哈 " ; 
System.out.println(str.toUpperCase()); 
System.out.println(str.toLowerCase());

这两个函数只转换字母。

代码示例: 字符串length()

String str = " hello%$$%@#$%world 哈哈哈 " ; 
System.out.println(str.length()); 

注意:数组长度使用数组名称.length属性,而String中使用的是length()方法

代码示例: 观察isEmpty()方法

System.out.println("hello".isEmpty()); 
System.out.println("".isEmpty()); 
System.out.println(new String().isEmpty());

String类并没有提供首字母大写操作,需要自己实现.

代码示例: 首字母大写

public static void main(String[] args) { 
 System.out.println(fistUpper("yuisama")); 
 System.out.println(fistUpper("")); 
 System.out.println(fistUpper("a")); 
 } 
 public static String fistUpper(String str) { 
 if ("".equals(str)||str==null) { 
 return str ; 
 } 
 if (str.length()>1) { 
 return str.substring(0, 1).toUpperCase()+str.substring(1) ; 
 } 
 return str.toUpperCase() ; 
 }

 再次强调:上面所有的操作都是产生了新字符串,原字符串是不可能改变的!!!

这个是成员方法,只能判断字符串的长度是否为0,不能判断null。

如果此时str = null;则肯定不能使用 str.isEmpty();       

那么该怎么判断呢?

 这里面的先后顺序不能换,只有不为空,才能引用方法。

写—个方法将字符串的首字母大写处理。
        

测试案例:

补充小知识:

关于StringBuilder类的具体使用:
 

首先来回顾下String类的特点: 任何的字符串常量都是String对象,而且String的常量一旦声明不可改变,如果改变对象内容,改变的是其引用的指 向而已。

 通常来讲String的操作比较简单,但是由于String的不可更改特性,为了方便字符串的修改,提供StringBuffer和 StringBuilder类。

StringBuffer 和 StringBuilder 大部分功能是相同的,我们主要介绍 StringBuffer

在String中使用"+"来进行字符串连接,但是这个操作在StringBuffer类中需要更改为append()方法:

public synchronized StringBuffer append(各种数据类型 b)

范例:观察StringBuffer使用

public class Test{ 
 public static void main(String[] args) { 
 StringBuffer sb = new StringBuffer(); 
 sb.append("Hello").append("World"); 
 fun(sb); 
 System.out.println(sb); 
 } 
 public static void fun(StringBuffer temp) { 
 temp.append("\n").append("www.bit.com.cn"); 
 } 
} 

 String和StringBuffer最大的区别在于:String的内容无法修改,而StringBuffer的内容可以修改。频繁修改字符串的 情况考虑使用StingBuffer。

为了更好理解String和StringBuffer,我们来看这两个类的继承结构:

可以发现两个类都是"CharSequence"接口的子类。这个接口描述的是一系列的字符集。所以字符串是字符集的子 类,如果以后看见CharSequence,最简单的联想就是字符串。 

注意:String和StringBuffer类不能直接转换。如果要想互相转换,可以采用如下原则:

String变为StringBuffer:利用StringBuffer的构造方法或append()方法

StringBuffer变为String:调用toString()方法。

 使用方法:

因为StringBulider类可以修改内容,因此具备一些String类不具备的修改内容的功能,除了拼接append方法外
比如:

a.字符串反转操作,sb提供的reverse();

public synchronized StringBuffer reverse()

 

b.删除指定范围的数据

public synchronized StringBuffer delete(int start, int end)

删除从start索引开始end之前的所有内容。[start,end)


示例代码:

注释:java里面的范围都是遵循左闭右开的原则。 这里范围的索引是从0开始的,所以第一个没有被删除。如果想删除这里的第七位数,右边需要写 7。左闭右开。

c.插入数据

public synchronized StringBuffer insert(int offset, 各种数据类型 b)

如果以后想字符串它进行拼接、翻转、删除、插入等等一系列操作,可以先讲String转换为StringBuffer,操作完成后再用toString转换为原来的String。

面试题:请解释String、StringBuffer、StringBuilder的区别

1. String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.

2. StringBuffer与StringBuilder大部分功能是相似的

3. StringBuffer采用同步处理,属于线程安全操作;StringBuilder未采用同步处理,属于线程不安全操作

注释:StringBuffer和StringBuilder除了线程安不安全的区别,其他完完全全一模一样。上面的案例用StringBuilder也一样可以。

小结

强调:一般情况下,要使用String类,就采用直接赋值的方式。要比较内容是否相等使用equals方法。除了特性情况,不然就别整些花里胡哨的操作了。

注意的点:

1. 字符串的比较,   ==  、 equals  、 compareTo 之间的区别.

2. 了解字符串常量池, 体会 "池" 的思想.

3. 理解字符串不可变

4. split 的应用场景

5. StringBuffer 和 StringBuilder 的功能.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、Java基础知识 1.Java有那些基本数据类型,String是不是基本数据类型,他们有何区别。 2.字符串的操作: 写一个方法,实现字符串的反转,如:输入abc,输出cba 写一个方法,实现字符串的替换,如:输入bbbwlirbbb,输出bbbhhtccc。 3.数据类型之间的转换 如何将数值型字符转换为数字(Integer,Double) 如何将数字转换为字符 如何取小数点前两位,并四舍五入。 4.日期和时间 如何取得年月日,小时分秒 如何取得从1970年到现在的毫秒数 如何获取某个日期是当月的最后一天 如何格式化日期 5.数组和集合 6.文件和目录(I/O)操作 如何列出某个目录下的所有文件 如何列出某个目录下的所有子目录 判断一个文件或目录是否存在 如何读写文件 7.Java多态的实现(继承、重载、覆盖) 8.编码转换,怎样实现将GB2312编码的字符串转换为ISO-8859-1编码的字符串。 9.Java中访问数据库的步骤,Statement和PreparedStatement之间的区别。 10.找出下列代码可能存在的错误,并说明原因: 二、JSP&Servlet技术 1.描述JSP和Servlet的区别、共同点、各自应用的范围 2.在Web开发中需要处理HTML标记时,应做什么样的处理,要筛选那些字符( & “”) 3.在JSP中如何读取客户端的请求,如何访问CGI变量,如何确定某个Jsp文件的真实路径。 4.描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理。 5.列出Jsp中包含外部文件的方式,两者有何区别。 6.说明Jsp中errorPage的作用,应用范围。 7.介绍在Jsp中如何使用JavaBeans。 8.简单介绍JSP的标记库 9.Jsp和Servlet中的请求转发分别如何实现。 三、J2EE相关知识 1.介绍J2EE、J2SE、J2SE的区别。 2.J2EE是一种技术还是一种平台,他提供了那些技术。 3.什么是Application Server,它有什么功能和优点。 4.简单介绍连接池的优点和原理。 5.Web.xml的作用 四、其他 1.Web安全性的考虑(表单验证、浏览器Basic方式的验证,应用程序的安全性,SSL,代码考虑) 2.简单介绍您所了解的MVC。 3.简单介绍所了解的XML。 4.文档和编码规范 5.Java中的分页、效率考虑。 6.简单介绍您所了解的structs。 1.xml在项目中的作用 2.s-EJB 与 e-EJB的区别 3.会话面的作用 4.cmp与bmp的优缺点 5.j2me程序的必需的几个部分 6.c/s与b/s的区别 7.构建一个connect pool,然后再调用它, 8.j2ee平台与dotnet平台的区别 9.ejb的life cycle 10.session bean 和 entity bean的区别 11.ejb中的transaction机制 12.synchronized (生产者和消费) 13.StringStringBuffer 14.Serializable 15.MVC (Struts的工作流程) 16.什么是MDA 17.tcp与udp的区别 18.链表与散列表和数组的区别 19.堆和栈的区别 20.ejb的分类及区别 21.你对现在软件业以及国内软件业的看法 22.谈谈java多线程 23.谈谈文件加密技术 24.软件开发生命周期 25.路由协议种类及特点 26.java的awt和swing组件的GUI设计的关键 27.对于java流的认识 28.简单描述一下awt与swing区别。 29.简述java编程中事件处理模式。 30.你编写过applet吗?applet的安全权限如何?试列举java application或者applet中与servlet/jsp通信可以采用的方式。 31.简述逻辑操作(如&,|)与条件操作(如&&,||)的区别。 32.简述 Java Server Page 和 Servlet 的联系和区别。 33.简述synchronized和java.util.concurrent.locks.Lock的异同 ? 34.EJB规范规定EJB中禁止的操作有哪些? 35.java除了8种基本类型外,在虚拟机里还有哪一种,有什么作用? 36.除了使用new关键字创建对象意外,试列举另外三种以上创建实例的方式? 37.classloader中,JDK的API、Classpath中的同web-inf中的class加载方式有什么区别? 38.列举三种以上垃圾回收算法,并比较其优缺点? 39.编写代码实现一个线程池 40.描述一下JVM加载class文件的原理机制? 41.试举例说明一个典型的垃圾回收算法? 42.请用java写二叉树算法,实现添加数据形成二叉树功能,并以先序的方式打印出来. 43.请写一个java程序实现线程连接池功能? 44.给定一个C语言函数,要求实现在java类中进行调用。 45.如何获得数组的长度? 46.访问修饰符“public/private/protected/缺省的修饰符”的使用 47.用关键字final修饰一个类或者方法时,有何意义? 48.掌握类和对象的概念,掌握面向对象编程的本质 49.静态变量和静态方法的意义,如何引用一个类的静态变量或者静态方法? 50.JAVA语言如何进行异常处理,关键字:thorws,throw,try,catch,finally 51.Object类(或者其子类)的finalize()方法在什么情况下被调用? 52.一个“.java”原文件中是否可以包括多个类(不是内部类)? 53.掌握内部类和接口的概念 54.StringTokenizer类的使用 55.数据结构,如何遍历List中的元素? 如果要按照键值保存或者访问数据,使用什么数据结构? 要掌握Collection相关的接口和类的使用 56.使用StringBuffer类与String类进行字符串连接时有何区别? 57.调用Thread类的destroy()方法有什么后果? 58.多线程,用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用? 59.使用socket建立客户端与服务器的通信的过程 60.JAVA语言国际化应用,Locale类,Unicode 61.描述反射机制的作用 62.如何读写一个文件? 63.在图形界面中,一个按钮如何处理鼠标点击事件? 64.在图形界面中,一个表格,如何实现编辑单元格时弹出下拉框? 65.如何加载图片? 66.什么是模态对话框? 67.阐述MVC的概念 68.GUI布局管理器的使用,FlowLayout,BorderLayout,GridBagLayout 69.如何构造一棵树?选择树的一个节点时,如何得到这个节点? 70.向编辑框中输入字符时,如何控制只输入整数? 71.描述使用JDBC连接数据库的过程 72.EJB分为几类?什么是BMP,CMP? 73.什么是JNDI? 74.ADO是什么?ActiveX数据对象,是一个应用级程序接口. 75.四种JDBC方式?目前的版本? 76.EJB有哪几种?区别是什么? 77.JavaBean与EJB有什么区别? 78.软件开发生命周期有哪几个阶段? 79.软件开发有哪些因素? 80.软件开发中如何进行版本控制? 81.UML中,类视图如何表示类中的继承与聚合? 82.客户端游标与服务器端游标的区别? 83.动态游标与静态游标的区别? 84.dotnet由哪几个基本框架组成? 85.Oracle中SGA是什么? 86.web servers是什么? 87.UNIX中QT是什么意思? 88.在软件开发生命周期中的哪个阶段开始测试? 89.dotnet与J2EE的比较? 90.什么是ActiveX? 91.Java中IDL是什么? 92.ISO9000和CMM是什么?IS09000和CMM(软件能力成熟度模型)认证是国际上通用的软件质量评估方法.CMM的五个成熟度等级。 第一,谈谈final, finally, finalize的区别。 final?修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载 finally?再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 finalize?方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现。 第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统)。 Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&page=1 注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象 第四,&和&&的区别。 &是位运算符。&&是布尔逻辑运算符。 第五,HashMap和Hashtable的区别。 都属于Map接口的类,实现了将惟一键映射到特定的值上。 HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。 Hashtable 类似于 HashMap,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为它是同步的。 第六,Collection 和 Collections的区别。 Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。 Collection是个java.util下的接口,它是各种集合结构的父接口。 第七,什么时候用assert。 断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为 true。如果表达式计算为 false,那么系统会报告一个 AssertionError。它用于调试目的: assert(a > 0); // throws an AssertionError if a <= 0 断言可以有两种形式: assert Expression1 ; assert Expression1 : Expression2 ; Expression1 应该总是产生一个布尔值。 Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试信息的 String 消息。 断言在默认情况下是禁用的。要在编译时启用断言,需要使用 source 1.4 标记: javac -source 1.4 Test.java 要在运行时启用断言,可使用 -enableassertions 或者 -ea 标记。 要在运行时选择禁用断言,可使用 -da 或者 -disableassertions 标记。 要系统类中启用断言,可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用断言。 可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。 第八,GC是什么? 为什么要有GC? (基础)。 GC是垃圾收集器。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一: System.gc() Runtime.getRuntime().gc() 第九,String s = new String("xyz");创建了几个String Object? 两个对象,一个是“xyx”,一个是指向“xyx”的引用对象s。 第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少? Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11; 第十一,short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错? short s1 = 1; s1 = s1 + 1;有错,s1是short型,s1+1是int型,不能显式转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。 第十二,sleep() 和 wait() 有什么区别? 搞线程的最爱 sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级 (b)正在运行的线程因为其它原因而阻塞。 wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。 第十三,Java有没有goto? Goto?java中的保留字,现在没有在java中使用。 第十四,数组有没有length()这个方法? String有没有length()这个方法? 数组没有length()这个方法,有length的属性。 String有有length()这个方法。 第十五,Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型? 方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。 第十六,Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别? Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。 equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。 第十七,给我一个你最常见到的runtime exception。 ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException 第十八,error和exception有什么区别? error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。 exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。 第十九,List, Set, Map是否继承自Collection接口? List,Set是 Map不是 第二十,abstract class和interface有什么区别? 声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。 接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。 第二十一,abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 都不能 第二十二,接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? 接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。 第二十三,启动一个线程是用run()还是start()? 启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。 第二十四,构造器Constructor是否可被override? 构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading。 第二十五,是否可以继承String类? String类是final类故不可以继承。 第二十六,当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 不能,一个对象的一个synchronized方法只能由一个线程访问。 第二十七,try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后? 会执行,在return前执行。 第二十八,编程题: 用最有效率的方法算出2乘以8等於几? 有C背景的程序员特别喜欢问这种问题。 2 << 3 第二十九,两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对? 不对,有相同的hash code。 第三十,当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 是值传递。Java 编程语言只由值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。 第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上? switch(expr1)中,expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。 第三十二,编程题: 写一个Singleton出来。 Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 一般Singleton模式通常有几种种形式: 第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。 public class Singleton {   private Singleton(){}   //在自己内部定义自己一个实例,是不是很奇怪?   //注意这是private 只供内部调用   private static Singleton instance = new Singleton();   //这里提供了一个供外部访问本class的静态方法,可以直接访问     public static Singleton getInstance() {     return instance;       } } 第二种形式: public class Singleton {   private static Singleton instance = null;   public static synchronized Singleton getInstance() {   //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次        //使用时生成实例,提高了效率!   if (instance==null)     instance=new Singleton(); return instance;   } } 其他形式: 定义一个类,它的构造函数为private的,所有方法为static的。 一般认为第一种形式要更加安全些 ---- Java面试题和答案 (http://www.bioon.net/dispbbs.asp?boardid=169&id=108010) -- 作者:jiajia1983 -- 发布时间:2005-3-9 17:29:00 -- Java面试题和答案 JAVA相关基础知识 1、面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。 2.继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。 3.封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 2、String是最基本的数据类型吗? 基本数据类型包括byte、int、char、long、float、double、boolean和short。 java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 3、int 和 Integer 有什么区别 Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。 原始类型 封装类 boolean Boolean char Character byte Byte short Short int Integer long Long float Float double Double 引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。 4、StringStringBuffer的区别 JAVA平台提供了两个类:StringStringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。 5、运行时异常与一般异常有何异同? 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。 6、说出Servlet的生命周期,并说出Servlet和CGI的区别。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。 与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。 7、说出ArrayList,Vector, LinkedList的存储性能和特性 ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。 8、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。 SessionBean在J2EE应用程序中被用来完成一些服务器端的业务操作,例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。 对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。 对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。 Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应的 Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之,很可能数个使用者在执行某个 Stateless Session Bean 的 methods 时,会是同一个 Bean 的 Instance 在执行。从内存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。 9、Collection 和 Collections的区别。   Collection是集合类的上级接口,继承与他的接口主要有Set 和List. Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 10、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 11、HashMap和Hashtable的区别。 HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。 HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。 HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。 最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。 12、final, finally, finalize的区别。   final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 finally是异常处理语句结构的一部分,表示总是执行。
超级万年历 1.课程设计的目的 《JAVA程序设计》是计算机相关专业的必修专业基础课程,其实践性、应用性很强。实 践教学环节是必不可少的一个重要环节。本课程的程序设计专题实际是计算机相关专业 学生学习完《JAVA程序设计》课程后,进行的一次全面的综合训练,JAVA程序设计的设计 目的是加深对理论教学内容的理解和掌握,使学生较系统地掌握程序设计及其在网络开 发中的广泛应用,基本方法及技巧,为学生综合运用所学知识,利用软件工程为基础进 行软件开发、并在实践应用方面打下一定基础。编写一个万年历理解图像界面的基本组 织窗口,以及类、方法的调用,以及添加控件、并在窗口中显示,可以对年份、月份、 当前的时间进行查询方便用户的使用。 2.设计方案论证 2.1需求分析 本次课程设计是编写一个万年历程序,主要目的是加强对Java的实际运用,了解图形 用户界面的基本组件窗口、按纽(JButton)、标签(JLabel)、下拉表组件(JComboBox)、 文本框(TextBox)、选择框、查询事件的处理,菜单的设计还有日期的计算等的使用方法 ,了解如何使用布局管理器对组件进行管理,以及如何使用Java的事件处理机制。 万年历是一个强大的日历系统,通过它可以实现对过去,现在以及将来日期的查找,通 过在年份对应的下拉菜单中选择要查询的年份,再相应的在月份对应的下拉菜单选择要 查询的月份,则可得到相应的日历。此外,还可以显示出数字时间,很方便用户的查询 。 本实验是对图形用户界面,布局管理器的综合运用,理解JAVA的时间处理机制,编写 独立运行的窗口。 2.2概要设计 本程序涉及三个类,MainFrame为显示日期部分的类,是程序中的主类,ClockActio n 是对所要查询的年份及其月份进行选择的类,Clock是对当前时间进行显示的类,位与整 个界面的底部,程序运行时,只要运行MainFrame即可显示出日期以及时间的详细信息。 以下是对这三个类的具体说明。 2.2.1自定义类说明 (1) ClockAction类 作用:获取当前下拉列表中所选择的信息 实现的接口:ActionListener ActionListener用于接收操作事件的侦听器接口。使用该类创建的对象可使用组件的 addActionListener 方法向该组件注册。在发生操作事件时,调用该对象的 actionPerformed 方法。ActionEvent指示发生了组件定义的动作的语义事件。当特定于组件的动作(比如 被按下)发生时,由组件生成此高级别事件。事件被传递给每一个 ActionListener 对象,这些对象是使用组件的 addActionListener 方法注册的,用以接收这类事件。 ClockAction类的具体实现如下: //对当前所选年份、月份的查询 class ClockAction implements ActionListener { public void actionPerformed(ActionEvent arg0) { int c_year, c_month, c_week; // 得到当前所选年份 c_year = Integer.parseInt(com1.getSelectedItem().toString()); // 得到当前月份,并减1,计算机中的月为0-11 c_month = Integer.parseInt(com2.getSelectedItem().toString())-1; // 调用函数use,得到星期几 c_week = use(c_year, c_month); // 调用函数Resetday Resetday(c_week, c_year, c_month); } } (2) MainFrame类 作用:主类 继承的父类:JFrame 实现的接口:没有 JFrame是MainFrame的父类,当用户试图关闭窗口时,JFrame 知道如何进行响应。用户关闭窗口时,默认的行为只是简单地隐藏 JFrame。在多屏幕环境中,可以在不同的屏幕设备上创建一个 JFrame。 主要方法说明: public static void main(String[] args) { JFrame.setDefaultLookAndFeelDecorated(true); new MainFrame(); } (3) Clock类 作用:显示时间的类 继承的父类:Canvas 实现的接口:Runnable Canvas是Clock的父类,它表示屏幕上一个空白矩形区域,应用程序可以在该区域内 绘图,或者可以从该区域捕获用户的输入事件。Runnable接口由Clock类来实现,设计该 接口的目的是为希望在活动时执行代码的对象提供一个公共协
实验指导书 实验名称:包、接口与异常处理 学时安排:2 实验类别:综合设计型实验 实验要求:1人1组  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ 一、实验目的 1、掌握java字符串处理方法。 2、掌握java面向对象的概念。 3、掌握java自定义异常和处理。 4、 通过实验,对Java程序的开发有一个深入了解。 二、实验内容 1.阅读并分析程序TestException.java。(见附件PPT文件) 2.设计一个程序,其功能是从命令行输入整数字符串,再将该整数字符串转换为整数, 输入的数据可能具有以下格式:12345、123 45、123xyz456 3.编写一个四则运算程序,要求用户输入一个x值和一个y值,以及一个四则运算符。如 果用户输入正确,则给出运算结果,如果输入错误,则给出出错警告。(利用异常处理 编程,尽量使用java现成的异常类,如没有可自定义异常类 ) 三、程序代码 1. public class TestException { public TestException() { } boolean testEx() throws Exception{ boolean ret = true; try{ ret = testEx1(); }catch (Exception e){ System.out.println("testEx, catch exception"); ret = false; throw e; } finally{ System.out.println("testEx, finally; return value="+ret); return ret; } } boolean testEx1() throws Exception{ boolean ret = true; try{ ret = testEx2(); if (!ret){ return false; } System.out.println("testEx1, at the end of try"); return ret; }catch (Exception e){ System.out.println("testEx1, catch exception"); ret = false; throw e; } finally{ System.out.println("testEx1, finally; return value="+ret); return ret; } } boolean testEx2() throws Exception{ boolean ret = true; try{ int b=12; int c; for (int i=2;i>=-2;i--){ c=b/i; System.out.println("i="+i); } return true; }catch (Exception e){ System.out.println("testEx2, catch exception"); ret = false; throw e; } finally{ System.out.println("testEx2, finally; return value="+ret); return ret; } } public static void main(String[] args) { TestException testException1 = new TestException(); try{ testException1.testEx(); }catch(Exception e){ e.printStackTrace(); } } } 2. import java.util.*; public class test { public static void main(String args[]) { int i, number=0; String str; try { for(i=0;i<args.length;i++) { str=args[i]; number=Integer.parseInt(str); System.out.printf("第%d个字符转换为整数后:%d\n",i+1,number); } } catch(NumberFormatException e) { System.out.println("输入字符串不正确!"); } } } 3. import java.io.*; import java.util.*; public class ExceptionExam { void addition(double x,double y) //加法运算

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值