【阿里云】Java面向对象开发课程笔记(三)——String类基本特点

1. String类基本特点

1.1 String类两种实例化方式

  String可以直接采用赋值的形式进行处理,与基本数据类型相似。
范例:直接赋值实例化对象

代码

public class StringDemo {
    public static void main(String args[]){
        //str是一个对象,“hello”保存在对内存之中
        String str = "hello";
        System.out.println(str);
        }
}
  • 输出结果
hello

  String本身是一个类,类中一定会提供构造方法,String类提供了以下构造方法:

  • 构造:public String (String str);
    第一个String是类名称,第二个String是参数类型

代码

public class StringDemo {
    public static void main(String args[]){
        // 该过程复合于传统做法,有类之后通过关键字new进行对象实例化
        String str =  new String ("hello");
        System.out.println(str);
        }
}
  • 输出结果
hello

1.2 字符串比较

范例:基本数据类型比较

代码

public class StringDemo {
    public static void main(String args[]){
        int x = 10;
        int y = 10;
        System.out.println(x == y );
        }
}
  • 输出结果
true

范例:String类进行“==”比较

代码

public class StringDemo {
    public static void main(String args[]){
        String str1 = "hello";
        String str2 = new String ("hello");
        System.out.println(str1 == str2 );
        }
}
  • 输出结果
false

内存分析:
这里写图片描述

  “==”本身比较的是数值,但如果用在对象中,那么比较的就是对象所保存的内存地址的数值。属于地址数值比较,而并没有比较对象的内容,所以不能使用。
  进行内容比较,必须采用String提供的方法(暂时变形)。

  • 内容比较:public boolean equals(String str);equals()区分大小写。

范例:进行字符串内容比较

代码

public class StringDemo {
    public static void main(String args[]){
        String str1 = "hello";
        String str2 = new String ("hello");
        System.out.println(str1.equals(str2));
        }
}
  • 输出结果
true

Q:请解释String类中“==”和“equals()”的区别。

  • “==”:进行的是数值比较,比较的是两个字符串内存地址的数值;
  • “equals()”: 进行字符串内容的比较。

1.3 字符串常量是String类的匿名对象

  所有语言的底层上面都不可能提供有直接的字符串类型。现在所谓的字符串只是高级语言提供给用户方便开发的支持。在java中也没有直接提供有字符串常量的概念,所有使用“ “” ”定义的内容本质上都是String的匿名对象。
范例:观察字符串操作

代码

public class StringDemo {
    public static void main(String args[]){
        String str = "hello";
        System.out.println("hello".equals(str));
        }
}
  • 输出结果
true

  “String str = “hello” ;”本质上是将一个匿名的String类对象设置有名字,而且匿名对象保存在堆内存中。
提醒:如果要判断用户输入的字符串是否等同于指定的字符串,那么一定要将字符串写在前面。
  在数据接收时必须要考虑用户没有输入数据的问题,以下述代码为例,用户没有输入,则一定出现“NullPointException”问题。

  • 比较的操作方法1:
    代码
public class StringDemo {
    public static void main(String args[]){
        String input = null; // 假如由用户输入
        System.out.println(input.equals("hello"));
        }
}
  • 输出结果
NullPointException
  • 任何字符串常量都是String匿名对象,所以该对象永远不可能为null。

代码

public class StringDemo {
    public static void main(String args[]){
        String input = null; // 假如由用户输入
        System.out.println("hello".equals(input));
        }
}
  • 输出结果
false

建议:把字符串写在前面。

1.4 String两种实例化的区别

1.采用直接赋值
String str = “hello”;
内存分析:
这里写图片描述
按照此模式继续进行如下操作。

代码

public class StringDemo {
    public static void main(String args[]){
        String str1 = "hello";
        String str2 = "hello";
        String str3 = "hello";
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
        System.out.println(str2 == str3);  
        }
}
  • 输出结果
true
true
true

内存分析:
这里写图片描述
  从结果分析,它们指向了同一个内存地址。String类的设计使用了共享设计模式.
  在JVM底层实际上会自动维护一个对象池(字符串对象池),如果采用直接赋值的模式进行String类实例化操作,那么该实例化对象将自动保存到对象池中,如果下次继续使用了直接赋值的模式,声明了String类的对象,如果对象池中有指定内容,那么将直接引用,如果没有,则开辟新的对象并保存在对象池之中以供下次使用。(所谓的对象池就是一个对象数组)
范例:观察与字符串常量比较

代码

public class StringDemo {
    public static void main(String args[]){
        String str = "hello";
        System.out.println("hello" == str);
        System.out.println("hello" == "hello");
        }
}
  • 输出结果
true
true

  此时全部返回true,一方面与共享模式有关,一方面与JDK的版本有关,会存在差异。
2.采用构造方法
  类对象采用构造方法进行实例化是标准做法。
范例:观察与字符串常量比较

代码

public class StringDemo {
    public static void main(String args[]){
        String str =  new String ("hello");
        }
}

内存分析:
这里写图片描述
  如果使用构造方法将会开辟两块堆内存空间,并且有一块堆内存空间会成为垃圾空间,也会对字符串共享产生影响。

代码

public class StringDemo {
    public static void main(String args[]){
   // 该字符串常量并没有保存在对象池之中
        String str1 =  new String ("hello");
        String str2 = "hello";
        System.out.println(str1 == str2);
        }
}
  • 输出结果
false

进入对象池操作:public String intern();

代码

public class StringDemo {
    public static void main(String args[]){
        String str1 =  new String ("hello").intern();
        String str2 = "hello";
        System.out.println(str1 == str2);
        }
}
  • 输出结果
true

内存分析:
这里写图片描述
Q:请解释String类中两种实例化方式的区别:

  • 直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以保存在对象池中以供下次使用。
  • 构造方法:会开辟两块堆内存空间,一块会成为垃圾,并且不会保存在对象池中,需采用intern()方法手工入池。

使用直接赋值。

1.5 字符串常量不可变更

  所有语言对于字符串的底层实现都是字符数组,数组最大的缺陷就是长度固定。字符串常量的内容是不可能改变的。
范例:观察如下代码

代码

public class StringDemo {
    public static void main(String args[]){
        String str = "hello";  
        str = str + "world";
        str += "!!!";
        System.out.println(str);
        }
}
  • 输出结果
helloworld!!!

  以上字符串的变更时字符串对象的变更而不是字符串的内容,以上代码执行操作如下:
这里写图片描述
  字符串上没有发生任何变化,但是字符串对象的引用一直在改变,而且会形成很多垃圾,由于String类的这个特点,如下代码不应出现:

代码

public class StringDemo {
    public static void main(String args[]){
        String str = "hello";  
        for(int x = 0 ; x < 1000; x++){
                str += x;
        }
        System.out.println(str);
        }
}

  如果很多人都像这样使用,那么产生的垃圾就相当可观了。

2.总结

1.字符串使用采用直接赋值模式完成;
2.字符串比较使用equals()方法实现;
3.字符串内容不要改变太多。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值