You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

10 KiB

1. 类抽象与封装

Class abstraction means to separate class implementation from the use of the class. The creator of the class provides a description of the class and let the user know how the class can be used. The user of the class does not need to know how the class is implemented. The detail of implementation is encapsulated and hidden from the user.

类抽象的含义是分离类的实现细节和类的使用这如何理解Java类的编写者为使用该类的用户提供说明让使用者知道如何使用该类但是使用者并不知道类的具体实现。类的具体实现被封装和隐藏起来使用者并不用知道。对于使用者只需要知道如何使用该类的功能而不用知道类是如何实现这些功能的。

利用生活当中的例子:你去修车,给修车师傅说明你需要处理什么问题(外部接口调用),修车师傅去处理你车的故障(运行封装在类内部的功能函数等),最后告知你处理结果(外部接口调用返回)。

image-20230313180426040

修车师傅是一个对象,你只告诉修车师傅什么故障,剩下的事情交给他来处理,会给你一个处理结果。你并不关系修车师傅是如何修车的。这就是类的抽象与封装。

其实最常用的抽象和封装是函数,只不过类把这个概念提升到了另外一个层次;函数只是对方法(行为)进行抽象与封装,类则是把相关的数据和方法进行打包和分类,这样更便于使用。不光如此,后面将要学习的继承和接口将极大的减少代码的冗余,便于代码的重复使用。

C中还有一种封装就是静态库和动态库是把相关函数的编译结果进行打包用于外部调用但是隐藏内部实现细节不过仍然局限于函数。

其他例子:

  1. Designing the Loan Class
  2. The Course Class
  3. StackOfIntegers Class

2. 封装类型 Wrapper class

回忆一下前面我们学到的基本类型primitive 类型这些类型包括所有的以小写字母大头的Java预定义类型。

  1. byte
  2. short
  3. int
  4. long
  5. float
  6. double
  7. boolean
  8. char

使用这些类型和C中对应的这些类型几乎完全一致这些类型不是引用类型不需要new 关键字来生成对象),在赋值与参数传递的时候采用的是值传递的方法。

primitive基本类型也叫原始类型

在Java中有一句话叫做一切皆对象。Java中也存在与基本类型对应的引用类型叫做封装类型这些类型是以大写字母开头的。

Primitive type Wrapper type(class)
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character
  1. The wrapper classes do not have no-arg constructors. 封装类型没有不带参数的构造函数;
  2. The instances of all wrapper classes are immutable. 所有封装类型的对象都是immutable。

封装类型我们前面用过一些,不过是其静态的成员函数。例如:Integer.parseInt("1234"),`Double.parseDouble("3.14"),等这样的函数;凡是数值类型的封装类型都有类似的函数把一个字符串转换成对应的基本类型(原始类型)。

Character类的Character.isDigit(char)Character.isLetter(char)这些函数前面也接触到过。

2.1. 数值类封装类型

2.1.1. 数值类封装类型的构建

既然封装类型是引用类型那么就可以使用new关键字来生成一个对应的对象。

		Byte b = new Byte((byte) 10); 			// 这是合法的但是必须转换成byte类型
		Short s = new Short((short) 100);		// 这是合法的但是必须转换成short类型
		Integer i = new Integer(200);
		Long l = new Long(999999);
		Float f = new Float(3.14);
		Double d = new Double(33.33);	

注意新版本的Java已经把通过构造函数生成数值类封装类型标记为@Deprecated因此将来可能会取消变成不合法的。新版本的Java对于数值类封装类型建议使用对应类型的静态函数valueOf()类构造。valueOf()函数有多个重载的版本,请查看对应的文档。

数值类封装类型有静态函数valueOf可以从相应的原始类型或者字符串来生成对应数值类封装类型的对象

		Integer i = Integer.valueOf(100);
		Integer i = Integer.valueOf("100");

但是这样的写法太复杂了,我们可以简单的写成:

		Byte b = 10; 			// 这是合法的
		Short s = 100;
		Integer i = 200;
		Long l = 999999L;		// 字面量量缺省是int类型需要标记成L长整型
		Float f = 3.14F;		// 字面量是double类型需要标记成F浮点类型
		Double d = 33.33;

2.1.2. 数值类封装类型的转换

数值类封装类型和原始类型间可以自由转换与赋值:

		int a = 100;
		Integer i = a;
		i = 200;
		a = i;

注意:不同的类型的数值类封装类型对象间不能赋值

		int a = 100;
		long b = a;
		a = (int) b;
		
		Integer i1 = 100;
		Long l1 = 200L;
		
		i1 = l1;				// 非法
		l1 = i1;				// 非法

同时原始类型的强制类型转换方式类似C的方式不能用在数值类封装类型中

		Integer i1 = 100;
		Long l1 = 200L;
		
		i1 = (Integer)l1;			// 非法
		l1 = (Long)i1;				// 非法

不同数值类封装类型间的类型转换应该使用实例函数byteValue()shortValue()intValue()longValue() floatValue()doubleValue() 这些函数:

		Integer i = 100;
		Byte b = i.byteValue();
		Short s = i.shortValue();
		long l = i.longValue();
		Float f = s.floatValue();
		double d = f.doubleValue();

2.1.3. 数值类封装类型的常量

image-20230311093817254

例如Integer和Double其他数值类一样都有MAX_VALUE和MIN_VALUE两个常量且是静态的。

2.1.4. 特殊值null

在使用数值类封装类型的时候要特别注意封装类型是引用类型因此可能有一个特殊的值null

3. 字符串

3.1. join和split

关于String的大多特性前几章已经覆盖了。这一章中有一个String的split函数在数组中给大家进行了初步的说明。

例如一个以空格分隔的字符串,我们希望把每一段切取出来,形成一个数组,这时我们使用:

        String string = "AAA BBB CCC";
        string.split(" ");

split的参数是一个正则表达式这个我们可以不用掌握这里如果字符串是空格分隔写入一个空格的字符串就可以了标识拆分的字符串。

函数返回是一个 String[] 类型的数组,你得到的是 {"AAA", "BBB", "CCC" } ,注意,不包含分隔字符串。

相对的,可以使用 join 函数把一个字符串数组以一定的分隔符连接成一个新的字符串。

split 是实例函数join是静态函数。

public class Test {
	public static void main(String[] args) {
		String string = "AAA BBB CCC";
		String sAry[] = string.split(" ");
		for (String s : sAry) {
			System.out.println(s);
		}
		
		String newStr = String.join(":", sAry);
		
		System.out.println(newStr);
	}
}

3.2. 正则表达式(了解)

正则表达regular expression式是用来对字符串进行模糊匹配的功能非常强大但规则比较难一点。

You can match, replace, or split a string by specifying a pattern. This is an extremely useful and powerful feature, commonly known as regular expression. Regular expression is complex to beginning students. For this reason, two simple patterns are used in this section. Please refer to Supplement III.F, “Regular Expressions,” for further studies.

在用到字符串对比和查找的地方都可以用到正则表达式,例如:

"Java".matches("Java");					// 字符串的字面量本来就是一个字符串对象,可以在其上使用字符串的实例函数
"Java".equals("Java");
"Java is fun".matches("Java.*");
"Java is cool".matches("Java.*");

如果大家有兴趣,可以自己学习正则表达式。

3.3. StringBuilder 和 StringBuffer

String是immutable表示其值是不能更改的一旦给一个String类型的引用变量赋值相当于产生了一个新的对象这样对于一个需要经常变化的字符串操作来说是不经济的耗费系统资源因此有了StringBuilder和StringBuffer。这两个类维护了一个字符串的缓冲区且内容是可以随时进行修改的也可以方便的转换成String类型。

例如:

import java.util.Scanner;

public class PalindromeIgnoreNonAlphanumeric {
	/** Main method */
	public static void main(String[] args) {
		// Create a Scanner
		Scanner input = new Scanner(System.in);

		// Prompt the user to enter a string
		System.out.print("Enter a string: ");
		String s = input.nextLine();

		// Display result
		System.out.println("Ignoring non-alphanumeric characters, \nis " + s + " a palindrome? " + isPalindrome(s));
	}

	/** Return true if a string is a palindrome */
	public static boolean isPalindrome(String s) {
		// Create a new string by eliminating non-alphanumeric chars
		String s1 = filter(s);

		// Create a new string that is the reversal of s1
		String s2 = reverse(s1);

		// Compare if the reversal is the same as the original string
		return s2.equals(s1);
	}

	/** Create a new string by eliminating non-alphanumeric chars */
	public static String filter(String s) {
		// Create a string builder
		StringBuilder stringBuilder = new StringBuilder();

		// Examine each char in the string to skip alphanumeric char
		for (int i = 0; i < s.length(); i++) {
			if (Character.isLetterOrDigit(s.charAt(i))) {
				stringBuilder.append(s.charAt(i));
			}
		}

		// Return a new filtered string
		return stringBuilder.toString();
	}

	/** Create a new string by reversing a specified string */
	public static String reverse(String s) {
		StringBuilder stringBuilder = new StringBuilder(s);
		stringBuilder.reverse(); // Invoke reverse in StringBuilder
		return stringBuilder.toString();
	}
}

4. 本章重点

  1. 掌握原始类型对应的封装类型;
  2. 掌握数值封装类型和原始类型,字符串的相互转换;
  3. 了解StringBuilder 的使用