JAVA基础知识(五)

5.4 构造方法

构造方法的主要作用就是为类中的属性初始化。

类名称 对象名称 = new 类名称()
从格式中发现,在最后有一个类名称()的代码,在程序中只要是一看见有“()”就表示调用方法,那么这个方法实际上就是要表示调用构造方法,构造方法可视为一种特殊的方法,他的定义方式与普通方法类似,其语法如下:

构造方法定义格式

class 类名称{
	访问权限 类名称(类型1 参数1,类型2 参数2,···){
	    程序语句;
	    ··· //构造方法没有返回值
	}
}

在构造方法的声明中一定要牢记以下几点:
(1)构造方法的名称必须与类名称一致;
(2)构造方法的声明处不能有任何返回值类型的声明;
(3)不能再构造方法中使用return返回一个值。

在Java中如果一个类中没有明确的声明一个构造方法则在编译的时候会直接生成一个无参数的、什么都不做的构造方法。

关于自动生成构造方法的说明。
在一个类中如果已经明确地声明了一个构造方法,那么程序在编译时将不会再生成默认的构造方法,即:一个类中至少会存在有一个构造方法。

与普通方法一样,构造方法也是可以重载的,由于构造方法名称本身要求与类名称保持一致,所以只要每个构造方法的参数类型或参数个数不同,就可以实现重载了。

注意编写顺序。
在一个类中对构造方法重载时,所有的重载方法按照参数的个数由多到少,或者由少到多排列,即:以下的两种排列方式都是规范的:

public Person(){}
public Person(String name){}
public Person(String name,int age){}

public Person(String name,int age){}
public Person(String name){}
public Person(){}

以上的两种写法都是按照参数的个数进行排列的。虽然不按照以上方式排列,不是语法错误,但是考虑到程序阅读的方便,请严格遵守以上规定。

5.5 匿名对象

**“匿名对象”,就是没有明确给出名字的对象。**一般匿名对象只使用一次,而且匿名对象只在堆内存中开辟空间,而不存在栈内存的引用。

使用了“new Person(“张三”,30)”语句,这实际上就是一个匿名对象,与之前声明的对象不同,此处由于没有使用任何栈内存引用此块堆内存空间,所以该对象使用一次之后就等待被垃圾回收机制回收。

匿名对象的作用。
匿名对象在实际的开发中基本上都是作为其他类的实例化对象的参数传递的,在后面的Java应用部分的很多地方都是可以发现其用法的。而且匿名对象实际上就是一个堆内存空间,对象不管是匿名的还是非匿名的,都必须在开辟堆内存空间之后才可以使用。

5.6 String类

5.6.1 实例化String类对象

对于String可以采用直接赋值的方式进行操作,如下面的代码。

直接为String赋值

public class StringDemo01{
     public static void main(String args[]){
         String name = "LiXingHua";  //实例化String对象
	 System.out.println("姓名:"+name);//输出字符串的内容
     }
}

在String类的使用上还有另外一种形式的实例化方法,就是直接调用String类中的构造方法,String类存在以下的构造方法:
public String(String original)

使用第二种String的实例化方式

public class StringDemo02{
     public static void main(String args[]){
         String name = new String("LiXingHua");  //实例化String对象
	 System.out.println("姓名:"+name);//输出字符串的内容
     }
}
5.6.2 String对象的内容比较

使用“==”进行内容比较
对于基本数据类型(如int型变量)可以通过“==”进行内容的比较,代码如下。

public class StringDemo03{
	public static void main(String args[]){
		int x=30;
		int y=30;  //声明一个整形变量
		System.out.println("两个数字的比较结果:"+(x==y));
    }
}

两个数字的比较结果:true

使用“ == ”比较字符串的内容

public class StringDemo04 {
	public static void main(String[] args) {
		String str1 = "hello";				//直接赋值
		String str2 = new String("hello");  //通过new赋值
		String str3 = str2;					//传递引用
		System.out.println("str1==str2-->"+(str1==str2)); //false
		System.out.println("str1==str3-->"+(str1==str3)); //false
		System.out.println("str2==str3-->"+(str2==str3)); //true
	}
}

str1 == str2–>false
str1 == str3–>false
str2 == str3–>true
从这里可以看出,每个String对象的内容实际上都是保存在堆内存之中的,而且堆中的内容是相等的。但对于str1和str2来说,其内容分别保存在了不同的空间,所以即便内容相等,但是地址的值也是不相等的,“==”是用来进行数值的比较,所以str1和str2比较不相等。那么str2和str3呢?从程序中可以发现str2和str3指向了同一个空间,是同一个地址,所以最终结果str2和str3的地址值是相等的,同理,str1和str3的地址值也不相等,所以返回了false。从上面的结果中可以清楚的发现“==”是用来进行地址值比较的。

如何判断两个字符串的内容是否相等呢?此时就可以利用String中专门提供的方法(String是一个类,则会存在各种方法):
public boolean equals(String str)。

equals()方法是会区分字符串大小写字母的,也就是说“H”与“h”比较的结果为false。

在实际的开发之中,由于字符串的地址是不好确定的,所以不要使用“==”比较,所有的比较都要通过equals()方法完成。

常见面试题分析:请解释String类中“ == ”和“equals()”方法比较的区别。
(1)“==”是Java提供的关系运算符,主要的功能是进行数值相等判断的,如果用在了String对象上表示的是内存地址数值的比较。
(2)equals()方法是由String提供的一个方法,此方法专门负责进行字符串内容的比较。

5.6.3 String类两种对象实例化方式的区别

String有两种实例化方式,一种是通过直接赋值的方式,另一种是使用标准的new调用构造方法完成实例化,那么两种方式有什么区别?该使用哪种更好呢?
如果要想对以上问题进行解释,首先必须明白一个重要的概念,一个字符串就是一个String类的匿名对象,匿名对象就是已经开辟了堆内存空间的并可以直接使用的对象。

public class StringDemo06{
	public static void main(String[] args) {
	     System.out.println("\"hello\"equals\"hello\"-->"+("hello".equals("hello")));
	}
}

程序执行结果:
“hello"equals"hello”–>true
从程序的运行结果可以发现,一个字符串确实可以调用String类中的额方法,也就证明了一个字符串就是一个String类的匿名对象。

避免NullPointerException的比较操作。
在实际的工作开发中会出现这样一种情况:假设现在用户需要输入某一个字符串,而后判断该输入的内容是否为指定内容,如果用户输入信息还可以判断,而当用户不输入信息时如果处理不当就会出现NullPointerException,如下代码所示。
实例一:观察问题

public class StringDemo{
	public static void main(String[] args) {
	    String input =null; //假设这个内容由用户输入
	    if(input.equals("hello")){ //如果输入内容是hello,认为满足一个条件 
	    System.out.println("Hello World!!!");
	     }
	}
}

程序执行结果:
Exception in thread "main"java.lang.NullPointerException at StringDemo.main(StringDemo.java:4)
此时由于没有输入数据所以input的内容为null,而null对象调用方法的结果将直接导致“NullPointerException”,而这样的问题可以通过一些代码的变更来帮助用户回避。

实例二:回避NullPointerException问题

public class StringDemo{
	public static void main(String[] args) {
	    String input =null; //假设这个内容由用户输入
	    if("hello".equals(input)){ //如果输入内容是hello,认为满足一个条件 
	    System.out.println("Hello World!!!");
	     }
	}
}

此时程序直接利用了字符串常量来调用了equals()方法,因为字符串常量是一个String类的匿名对象,所以该对象永远不可能是null,所以将不会出现NullPointerException,特别需要提醒读者的是,equals()方法内部实际上也存在有null的检查。

对于String str1 =“hello”;
实际上就是把一个在对内存中开辟好的堆内存空间的使用权给了str1这个对象。
栈内存 堆内存
str1 ——> “hello”
直接赋值实例化String类对象
使用这种方式还有另外一个好处,那就是,如果一个字符串已经被一个名称所引用,则以后再有相同的字符串声明的时候,不会再重新开辟空间。

public class StringDemo04 {
	public static void main(String[] args) {
		String str1 = "hello"; //声明三个字符串变量,每个变量的内容都是一样的				
		String str2 = "hello";//声明三个字符串变量,每个变量的内容都是一样的		
		String str3 = "hello";//声明三个字符串变量,每个变量的内容都是一样的				
		System.out.println("str1==str2-->"+(str1==str2)); //true
		System.out.println("str1==str3-->"+(str1==str3)); //true
		System.out.println("str2==str3-->"+(str2==str3)); //true
	}
}

结果为
str1 == str2–>true
str1 == str3–>true
str2 == str3–>true

从程序运行结果可以发现,所有的字符串都使用了“==”进行了比较,所得到的结果都是true,那么也就是说这3个字符串指向的堆内存地址空间都是同一个,所以,String使用直接赋值的方式之后,只要是以后声明的字符串内容相同,则不会单独开辟新的内存空间。

技术穿越:String类所采用的设计模式为共享设计模式。
在JVM的底层实际上会存在有一个对象池(不一定只保存String对象),当代码中使用了直接赋值的方式定义了一个String类对象时,会将此字符串对象所使用的匿名对象入池保存,而后如果后续还有其他String类对象也采用了直接赋值的方式,并且设置了同样内容的时候,那么将不会开辟新的堆内存空间,而是使用已有的对象进行引用的分配,从而继续使用。

//使用new String()的方式实例化String对象

public class StringDemo08 {
	public static void main(String[] args) {
		String str = new String("hello");//通过关键字new实例化
	}
}

一个字符串就是String类的匿名对象,如果使用new关键字的话,不管如何都会再开辟一个新的空间,但是此时,空间的内容还是“hello",所以上面的代码实际上是开辟了两个内存空间,但真正使用的只是一个使用关键字new开辟的内存空间,另一个是垃圾空间。

对于字符串的操作最好采用直接赋值的方式完成,而不要采用构造方法传递字符串的方式完成。

常见面试题分析:请解释String类的两种对象实例化方式的区别。
(1)直接赋值(String str = “字符串”;):只会开辟一块堆内存空间,并且会自动保存在对象池之中以供下次重复使用;
(2)构造方法(String str = new String(“字符串”)):会开辟两块堆内存空间,其中一块空间将成为垃圾,并且不会自动入池,但是用户可以使用intern()方法手工入池。
在日后的所有开发中,String对象的实例化永远都采用直接赋值的方式完成。

5.6.4 字符串的内容不可改变

在使用String类进行操作的时候,字符串的内容一旦声明则不可改变。
一个String对象内容的改变实际上是通过内存地址的“断开-连接”变化完成的,而字符串中的内容并没有任何变化。

5.6.5 String类中常用方法

要学会参考文档。对于每一个文档的内容而言,它都包含以下几个主要组成部分。
(1)第一部分:类的定义及相关的继承结构。
(2)第二部分:类的一些简短的说明。
(3)第三部分:类的组成结构。
1.类之中的成员(Field Summary)。
2.类中的构造方法(Constructor Summary)。
3.类中的普通方法(Method Summary)。
(4)第四部分:对每一个成员、构造方法、普通方法的作用进行详细说明,包括参数的作用。

1.字符串与字符数组的转换
字符串可以使用toCharArray()方法变成一个字符数组,也可以使String类的构造方法把一个字符数组,变为一个字符串。

2.从字符串中取出指定位置的字符
可以直接使用String类中的charAt()方法取出字符串指定位置的字符。

3.字符串与byte数组的转换
字符串可以通过getByte()方法将String变为一个byte数组,之后可以通过String的构造方法将一个字节数组重新变为字符串。

4.取得一个字符串的长度
在String中使用length()方法取得字符串的长度。

length与length()。
“在数组操作中,使用length取得数组的长度,但是操作的最后没有‘()’。而字符串调用length()是一个方法,只要是方法后面都有‘()’”。

5.查找一个指定的字符串是否存在
在String中使用indexOf()方法,可以返回指定的字符串的位置,如果不存在则返回-1。

String类对于判断字符串是否存在的方法提供有contains()(public boolean contains(String str)),此方法直接返回boolean型数据。

6.去掉左右空格
在实际开发中,用户输入的数据中可能含有大量的空格,此时。使用trim()方法可以去掉字符串的左、右空格。

7.字符串截取
在String中提供两个substring()方法,一个是从指定位置截取到字符串结尾,另一个是截取指定范围的内容。

8.按照指定的字符串拆分字符串
在String中通过split()方法可以进行字符串的拆分操作,拆分的数据将以字符串数组的形式返回。

9.字符串的大小写转换
在用户输入信息时,有时需要统一输入数据的大小写,那么此时就可以使用toUpperCase()和toLowerCase()两个方法完成大小写的转换操作。

10.判断是否以指定的字符串开头或结尾
在String中使用startWith()方法可以判断字符串是否以指定的内容开头,使用endWith()方法可以判断字符串是否以指定的内容结尾。

11.不区分大小写进行字符串比较
在String中可以通过equals()方法进行字符串内容的比较,但是这种比较方法是区分的小写的比较,如果要完成不区分大小写的比较则可以使用equalsIgnoreCase()方法。

12.将一个指定的字符串,替换成其他的字符串
使用String的replaceAll()方法,可以将字符串的指定内容进行替换。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值