StringBuffer类
由于字符串是常量,因此一旦创建,其内容和长度是不可改变的。如果需要对一个字符串进行修改,则只能创建新的字符串。为了对字符串进行修改,Java提供了一个StringBuffer类(也称字符串缓冲区)。StringBuffer类和String类最大的区别在于它的内容和长度都是可以改变的。StringBuffer类似一个字符容器,当在其中添加或删除字符时,并不会产生新的StringBuffer对象。
案例学习StringBuffer类的常用方法:
public class Example08 {
public static void main(String[] args) {
System.out.println("1、添加------------------------");
add();
System.out.println("2、删除------------------------");
remove();
System.out.println("3、修改------------------------");
alter(); }
public static void add() {
StringBuffer sb = new StringBuffer(); // 定义一个字符串缓冲区
sb.append("abcdefg"); // 在末尾添加字符串
System.out.println("append添加结果:" + sb);
sb.insert(2, "123"); // 在指定位置插入字符串
System.out.println("insert添加结果:" + sb);
}
public static void remove() {
StringBuffer sb = new StringBuffer("abcdefg");
sb.delete(1, 5); // 指定范围删除
System.out.println("删除指定位置结果:" + sb);
sb.deleteCharAt(2); // 指定位置删除
System.out.println("删除指定位置结果:" + sb);
sb.delete(0, sb.length()); // 清空缓冲区
System.out.println("清空缓冲区结果:" + sb);
}
public static void alter() { StringBuffer sb = new StringBuffer("abcdef"); sb.setCharAt(1, 'p'); // 修改指定位置字符
System.out.println("修改指定位置字符结果:" + sb);
sb.replace(1, 3, "qq"); // 替换指定位置字符串或字符
System.out.println("替换指定位置字符(串)结果:" + sb);
System.out.println("字符串翻转结果:" + sb.reverse());
}
}
StringBuilder类
StringBuilder类也可以对字符串进行修改,StringBuffer类和StringBuilder类的对象都可以被多次修改,并不产生新的未使用对象,StringBuilder类是JDK5中新加的类,它与StringBuffer之间最大不同在于StringBuilder的方法是线程安全的,也就是说StringBuffer不能被同步访问,而StringBuilder可以。
案例对比StringBuilder和StringBuffer的运行效率
public class Example09{
private static final int TIMES = 100000;
public static void main(String[] args) {
Example09.testString();
Example09.testStringBuffer();
Example09.testStringBuilder();
}
//String时间效率测试
public static void testString() {
long startTime = System.currentTimeMillis();
String str = "";
for (int i = 0; i < TIMES; i++) {
str += "test";
}
long endTime = System.currentTimeMillis();
System.out.println("String test usedtime: "
+ (endTime - startTime));
}
//StringBuffer时间效率测试(线程安全)
public static void testStringBuffer() {
long startTime = System.currentTimeMillis();
StringBuffer str = new StringBuffer();
for (int i = 0; i < TIMES; i++) {
str.append("test");
}
long endTime = System.currentTimeMillis();
System.out.println("StringBuffer test usedtime: " + (endTime –
startTime));
}
//StringBuffer时间效率测试(非线程安全)
public static void testStringBuilder() {
long startTime = System.currentTimeMillis();
StringBuilder str = new StringBuilder();
for (int i = 0; i < TIMES; i++) {
str.append("test");
}
long endTime = System.currentTimeMillis();
System.out.println("StringBuilder test usedtime: " + (endTime -
startTime));
}
模拟用户登录案例
在使用一些APP时,通常都需要填写用户名和密码。用户名和密码输入都正确才会登录成功,否则会提示用户名或密码错误。 本例要求编写一个程序,模拟用户登录。程序要求如下:
(1)用户名和密码正确,提示登录成功。
(2)用户名或密码不正确,提示“用户名或密码错误”。
(3)总共有3次登录机会,在3次内(包含三次)输入正确的用户名和密码后给出登录成功的相应提示。超过3次用户名或密码输入有误,则提示登录失败,无法再继续登录。。 在登录时,需要比较用户输入的用户名密码与已知的用户名密码是否相同,本案例可以使用Scanner类以及String类的相关方法实现比较操作。
import java.util.Scanner;
public class userlogin {
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
for (int i = 1;i <=3;i++){
String username = "刘姝贤";//初始用户名
String password = "520hxr";//初始密码
System.out.println("用户名:");
String uname = sc.nextLine();
System.out.println("密码:");
String upassword = sc.nextLine();
if (uname.equals(username)&&upassword.equals(password)){//判断输入的与初始值是否相等
System.out.println("欢迎登录!");
break;
}else {
if (i == 3){//i等于3输入提示并退出
System.out.println("3次登录失败,用户无法继续登录");
}else {
System.out.println("用户名或密码错误,请重新输入!");
}
}
}
}
}
本例要求编写一个程序,模拟默认密码的自动生成策略,手动输入用户名,根据用户名自动生成默认密码。在生成密码时,将用户名反转即为默认的密码。
import java.util.Scanner;
public class examble02 {
public static void main(String[] args) {
//键盘输入一个字符串,用Scanner实现
Scanner sc = new Scanner(System.in);
System.out.println("请您输入用户名:");
String line = sc.nextLine();
//调用方法,用一个变量接收
String reverse = reverse(line);
//输出结果
System.out.println("恭喜"+line+"用户注册成功,您的初始密码为:"+reverse);
}
//定义一个方法实现字符串反转
public static String reverse(String s) {
String ss = "";
//在方法中将字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并且返回
for (int i = s.length()-1; i >=0; i--) {
ss+=s.charAt(i);
}
return ss;
}
}
StringBuilder类和StringBuffer类不同:
(1)String类表示的字符串是常量,一旦创建后,内容和长度都是无法改变的。而StringBuilder和StringBuffer表示字符容器,其内容和长度可以随时修改。在操作字符串时,如果该字符串仅用于表示数据类型,则使用String类即可,但是如果需要对字符串中的字符进行增删操作,则使用StringBuffer与StringBuilder类。如果有大量字符串拼接操作,不要求线程安全的情况下,采用StringBuilder更高效。相反如果需要线程安全则需要使用StringBuffer。
(2)对于euals()方法的使用我们已经有所了解,但是在StringBuffer类与StringBuilder类中并没有被Object类的equals()方法覆盖,也就是说,equals()方法对于StringBuffer类与StringBuilder类来言并不起作用。
StringBuffer:线程安全,效率略低
StringBuilder:非线程安全,效率更高。
System类
System类对读者来说并不陌生,因为在之前所学知识中,需要打印结果时,使用的都是“System.out.println();”语句,这句代码中就使用了System类。System类定义了一些与系统相关的属性和方法,它所提供的属性和方法都是静态的,因此,想要引用这些属性和方法,直接使用System类调用即可。
System类的常用方法如下表。
1.arraycopy()方法:用于将数组从源数组复制到目标数组,声明格式如下: static void arraycopy(Object src,int srcPos,Object dest,
int destPos,int length)
关于声明格式中参数的相关介绍如下: |
● src:表示源数组 |
● dest:表示目标数组。 |
● srcPos:表示源数组中拷贝元素的起始位置。 |
● destPos:表示拷贝到目标数组的起始位置。 ● length:表示拷贝元素的个数 |
注意:在进行数组复制时,目标数组必须有足够的空间来存放拷贝的元素,否则会发生角标越界异常
案例演示数组元素的拷贝:
public class examble10 {
public static void main(String[] args) {
int[] fromArray = { 10, 11, 12, 13, 14, 15 }; // 源数组
int[] toArray = { 20, 21, 22, 23, 24, 25, 26 }; // 目标数组
System.arraycopy(fromArray, 2, toArray, 3, 4); // 拷贝数组元素
// 打印拷贝后数组的元素
System.out.println("拷贝后的数组元素为:");
for (int i = 0; i < toArray.length; i++) {
System.out.println(i + ": " + toArray[i]);
}
}
}
2.currentTimeMillis()方法
currentTimeMillis()方法用于获取当前系统的时间,返回值是long类型的值,该值表示当前时间与1970年1月1日0点0分0秒之间的时间差,单位是毫秒,通常也将该值称作时间戳。
for循环的求和的案例计算程序运行时所消耗的时间:
public class examble11 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();// 循环开始时的当前时间
int sum = 0;
for (int i = 0; i < 1000000000; i++) {
sum += i;
}
long endTime = System.currentTimeMillis();// 循环结束后的当前时间
System.out.println("程序运行的时间为:"+(endTime - startTime)+"毫秒");
}
}
3.getProperties()和getProperty()方法
System类的getProperties()方法用于获取当前系统的全部属性,该方法会返回一个Properties对象,其中封装了系统的所有属性,这些属性是以键值对形式存在的。getProperty() 方法用于根据系统的属性名获取对应的属性值。
4.gc()方法
在Java中,当一个对象成为垃圾后仍会占用内存空间,时间一长,就会导致内存空间的不足。针对这种情况,Java中引入了垃圾回收机制。有了这种机制,程序员不需要过多关心垃圾对象回收的问题,Java虚拟机会自动回收垃圾对象所占用的内存空间。
class Person {
// 下面定义的finalize方法会在垃圾回收前被调用
public void finalize() {
System.out.println("对象将被作为垃圾回收...");
}
}
public class example13 {
public static void main(String[] args) { // 下面是创建了两个Person对象
Person p1 = new Person();
Person p2 = new Person();
// 下面将变量置为null,让对象成为垃圾
p1 = null;
p2 = null;
// 调用方法进行垃圾回收
System.gc();
for (int i = 0; i < 1000000; i++) {
// 为了延长程序运行的时间
}
}
}
Runtime类
Runtime类用于表示虚拟机运行时的状态,它用于封装JVM虚拟机进程。每次使用java命令启动虚拟机都对应一个Runtime实例,并且只有一个实例,因此在Runtime类定义的时候,它的构造方法已经被私有化了(单例设计模式的应用),对象不可以直接实例化。若想在程序中获得一个Runtime实例,只能通过以下方式: Runtime run = Runtime.getRuntime(); 由于Runtime类封装了虚拟机进程,因此,在程序中通常会通过该类的实例对象来获取当前虚拟机的相关信息。
方法声明 | 功能描述 |
getRuntime() | 该方法用于返回当前应用程序的运行环境对象。 |
exec(String command) | 该方法用于根据指定的路径执行对应的可执行文件 |
freeMemory() | 该方法用于返回Java虚拟机中的空闲内存量,以字节为单位。 |
maxMemory() | 该方法用于返回Java虚拟机的最大可用内存量。 |
availableProcessors() | 该方法用于返回当前虚拟机的处理器个数 |
totalMemory() | 该方法用于返回Java虚拟机中的内存总量 |
1.获取当前虚拟机信息 Runtime类可以获取当前Java虚拟机的处理器的个数、空闲内存量、最大可用内存量和内存总量的信息。
2.操作系统进程 Runtime类中提供了一个exec()方法,该方法用于执行一个dos命令,从而实现和在命令行窗口中输入dos命令同样的效果。例如,通过运行“notepad.exe”命令打开一个Windows自带的记事本程序。
package test;
import java.io.IOException;
public class examble15 {
public static void main(String[] args) throws IOException {
Runtime rt = Runtime.getRuntime(); // 创建Runtime实例对象
rt.exec("notepad.exe"); // 调用exec()方法
}
}
运行结果:
由于每个人的机器配置不同,该文件的打印结果可能不同,另外空闲内存数、可用最大内存数和内存总量都是以字节为单位计算的,上述运行结果已经将字节换算成了兆(M)。
Math类
方法声明 | 功能描述 |
abs() | 该方法用于计算绝对值 |
sqrt() | 该方法用于计算方根 |
ceil() | 该方法用于计算大于参数的最小整数 |
floor() | 该方法用于计算小于参数的最小整数 |
round() | 该方法用于计算小数进行四舍五入后的结果 |
max() | 该方法用于计算两个数的较大值 |
min() | 该方法用于计算两个数的较小值 |
random() | 该方法用于生成一个大于0.0小于1.0的随机值 |
sqrt() | 该方法用于计算开平方的结果 |
pow() | 该方法用于计算指数函数的值 |
public static void main(String[] args) {
System.out.println("计算绝对值的结果: " + Math.abs(-10));
System.out.println("求大于参数的最小整数: " + Math.ceil(5.6));
System.out.println("求小于参数的最大整数: " + Math.floor(-4.2));
System.out.println("对小数进行四舍五入后的结果: " + Math.round(-4.6));
System.out.println("求两个数的较大值: " + Math.max(2.1, -2.1));
System.out.println("求两个数的较小值: " + Math.min(2.1, -2.1));
System.out.println("生成一个大于等于0.0小于1.0随机值: " +
Math.random());
System.out.println("开平方的结果: "+Math.sqrt(4));
System.out.println("指数函数的值: "+Math.pow(2, 3));
}
}
Random类
方法声明 | 功能描述 |
Random() | 构造方法,用于创建一个伪随机数生成器 |
Random(long seed) | 构造方法,使用一个long型的seed种子创建伪随机数生成器 |
import java.util.Random;
public class Example17 {
public static void main(String args[]) {
Random r = new Random(); // 不传入种子
// 随机产生10个[0,100)之间的整数
for (int x = 0; x < 10; x++) {
System.out.println(r.nextInt(100));
}
}
}
本例要求编写一个程序,从键盘录入一个字符串,将字符串转换为二进制数。在转换时,将字符串中的每个字符单独转换为一个二进制数,将所有二进制数连接起来进行输出。 案例在实现时,要求使用Math类、String类以及Scanner等常见Java API的常用方法实现。
package test;
//本例要求编写一个程序,从键盘录入一个字符串,将字符串转换为二进制数。在转换时,将字符串中的每个字符单独转换为一个二进制数,将所有二进制数连接起来进行输出。
// 案例在实现时,要求使用Math类、String类以及Scanner等常见Java API的常用方法实现。
import java.util.Scanner;
public class test04 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入要转换的字符串:");
String ss = in.nextLine(); // 读入一整行输入的数
//定义一个二维数组。其中4代表每一行长度。ss.length()根据键盘录入的字符串有多少行
int[][] arr = new int[ss.length()][4];// 因为二进制至少是四位,所以每一行的长度为4
for (int i = 0; i<ss.length() ; i++){
// for循环遍历字符串,然后通过charAt()方法,获取每一个字符,在将其转换为int类型
int charss = (int) ss.charAt(i)-48; // 因为在ASCII码中0的值是48,1的值是49,所以减去48
// 转化成int后再用for循环获取每一个int类型的数进行转化成二进制赋值给数组.
// Math.pow()方法是Math类中求幂的方法。
for (int j = 0 ; j < 4 ; j++){
arr[i][j] = (int) ((charss/Math.pow(2,3-j))%2);// 2的辗转相除直到结果为1
}
}
System.out.println("转换为二进制数为:");
// 最后用双重for循环将结果打印在控制台
for (int i = 0 ; i < ss.length() ; i++){
for (int j = 0 ; j < 4 ; j++){
System.out.print(arr[i][j]);
}
}
}
}
方法声明 | 功能描述 |
double nextDouble() | 随机生成double类型的随机数 |
float nextFloat() | 随机生成float类型的随机数 |
int nextInt() | 随机生成int类型的随机数 |
int nextInt(int n) | 随机生成0~n之间int类型的随机数 |