String简介:
1、Java利用其JVM的支持制造了一种可以简单使用的String类
2、String这个类里面之所以可以保存字符串的主要原因是其中定义了一个数组,也就是说在String中的字符串中的每一个字符的数据都是保存在了数组之中。JDK1.8之前String类保存的是字符数组(char型),从JDK1.9开始String类之中的数组类型采用了byte类。即字符串就是对数组的一种特殊包装应用。
3、在String类里面除了可以使用直接赋值的形式为对象进行实例化还可以利用构造方法进行对象的实例化处理。
直接赋值:String str = "aaa"
构造方法:String str = new String("aaa");
字符串比较:
判断int型变量是否相等,用“==”来判断
对于String类相等的判断也可以使用"==",只是判断的会不准确。例:
String str1 = "aaa"
String str2 = new String("aaa");
system.out.println(sr1 == str2 )->false
要想实现准确的字符串相等判断,那么可以使用String类中所提供的一个比较方法,字符串比较:public boolean equals(String str);
system.out.println(sr1.equals(str2 ))->true
【重要】请解释String比较中“==”与equals()区别?
new开辟了新的内存空间
“==”进行的是数值比较,如果用于对象比较上比较的是两个内存的地址数值;
equals()是类所提供可以直接进行字符串内容判断的比较方法。
字符串常量是String类的匿名对象:
在程序开发过程中,整数默认int型,小数默认double型。对于字符串而言,任何使用“”定义的字符串常量实际上描述的都是一个String类的匿名对象。
String str = "mldn"
内存关系图:
所以,String类对象的直接赋值描述的是:将一个匿名对象设置一个具体的引用名字。
验证匿名对象的存在(对象可调用方法):
String str = "aaa";
System.out.println("aaa".equals(str));->true
故,程序中无字符串常量这种基本类型,有的只是String类的匿名对象。
【重要】equals()方法里面提供有一个可以回避null的判断,所以如果将字符串常量写在前面,那么在调用equals()方法时不会出现“NullPointerException”的错误,字符串是一个匿名对象,匿名对象一定是开辟好堆内存空间的对象。
String input = null;
System.out.println(input.equals("aaa"));->java.lang.NullPointerException
String input = null;
System.out.println("aaa".equals(input));->true
String类两种实例化方式区别:
1、直接赋值的对象实例化模式
String str = "aaa";
这种情况下只会开辟一块堆内存空间。
String strA = "aaa";
String strB = "aaa";
System.out.println(str1 == str2); -> true //地址判断
故,【重要】利用直接赋值实例化String的形式还可以实现同一个字符的共享操作。因为在Java程序底层提供了有一个专门的字符串池(字符串数组)。在采用直接赋值的处理过程之中,对于字符串可以实现池数据的自动保存,如果再有相同数据定义时可以减少对象的产生,以提升操作性能。
2、构造方法实例化
构造方法实例化是进行对象定义时的常见做法,String类为了满足设计的结构要求,也提供了构造方法实例化。
此时会开辟两块堆内存空间,但只会使用一块,另外一块由于字符串常量所定义的匿名对象将成为垃圾空间。
更换形式:
String strA = "aaa";
String strB = new String("aaa");
此时“aaa”匿名对象引用的是池中已有对象,并没有重新再开辟新的空间。new则开辟了新的内存空间。总之,此时只开辟了一块新的内存空间。
String str1 = "aaa";
String str2 = new String("aaa");
System.out.println(str1 == str2); -> false //即地址不同
可以发现构造方法实例化的对象实际上是属于一种自己专用的内存空间,并没有入池,但是在String类里面也提供有帮助开发者实现手工入池的处理情况:public String intern();
String str2 = new String("aaa").intern();
System.out.println(str1 == str2); -> true //实现入池(但啰嗦)
【重要】请解释String类两种对象实例化方式的区别?
直接赋值只会产生一个实例化对象,并且可以自动保存到对象池之中,以实现该字符串实例的重用。
构造方法实例化会产生两个实例化对象,并且不会自动化入池,无法实现对象重用,但是可以使用intern()方法手动入池。
=》使用直接赋值比较稳妥
String对象(常量)池
1、对象池的目的是实现数据的共享处理。分类:
静态常量池:程序在加载的时候会自动将此程序中保存的字符串、普通的常量、类和方法的信息等,全部进行分配。
运行时常量池:程序加载之后,里面可能有一些变量,为其提供的常量池。
静态常量池举例:
String str1 = "a.b.c";
String str2 = "a"+"b"+"c";
System.out.println(str1 == str2); -> true
该程序之中所给出的全部内容都是常量数据(字符串的常量都是匿名对象),所以最终在程序加载的时候,会自动帮助开发者处理好相应的连接,连接好之后,会发现其在对象池中存在,则会指向已有的内存空间。
运行时常量池举例:
String str1 = "a.b.c";
string b = "b"
String str2 = "a"+b+"c";
System.out.println(str1 == str2); ->false
此时,程序加载的时候并不确定b的内容,因为b是一个可修改的标量
字符串内容不可修改:
在String类之中包含的是一个数组,而数组长度不可变。
String str = "www.";
str += "mldn.";
str = str + "cn";
System.out.println(str); ->www.mldn.cn
根据内存分析理解不可修改的原因:
在处理过程中,字符串常量的内容没有发生改变,改变的是String类对象的引用,这种改变将有可能产生大量的垃圾空间。因此,在开发过程中不要进行对String类的频繁修改。
Java中主方法组成分析:
public static void main(String [] args){
}
public:访问权限,主方法是一切的开始点,开始点一定是公共的。
static:程序的执行是通过类名称完成的,所以表示此方法是由类直接调用
void:无返回值
main:系统定义好的方法名称
String [] args:字符串的数组,可以实现程序启动参数的接收。(在CMD中,java StringDemo "hello word" hello)