梅庄

java语言程序设计-基础篇-进阶篇-读书笔记3

CH10面向对象思考

数值包装类

将基本数据类型值作为对象处理

出于对性能的考虑,在java中基本数据类型不作为对象使用,因为处理对象需要额外的系统开销。
但Java中的许多方法需要将对象作为参数
Java提供方法将基本数据类型并入对象或包装成对象(e.g. int包装成Integer类,double包装成Double类,char包装成Character类)

大多数基本类型的包装类的名称与对应的基本數据类型名称一样,第一个字母要大 写。Integer 和 Character 例外。

包装类都包含了doubleValue()、floatValue(), intValue()、longValue()、shortValue() 和 byteValue()方法。这些方法将对象 “转换” 为基本类型值。

既可以用基本数据类型值也可以用表示数值的字符串来构造包装类。
例如

1
2
new Double(5.0)
new Double('5.0')

包装类没有无参构造方法。所有包装类的实例都是不可变的,这意味着一旦创建对象后,它们 的内部值就不能再改变。

  • 包装类都有常量MAX_VALUE和MIN_VALUE
  • 包装类都会包含方法doubleValue()floatValue()intValue()longValue()shortValue()。这些方法返回包装对象的doublefloatintlongshort

    例如

    1
    2
    new Doub1e(12.4).intValue() returns 12;
    new Integer(12).doubleValueC) returns 12.0;
  • 包装类包含方法compareTo用于比较两个数值,大于等于小于分别返回1,0,-1

    例如

    1
    2
    3
    new Doub1e(12.4).compareTo(new Doub1e(12.3)) returns 1;
    new Double(12.3).compareTo(new Doub1e(12.3)) returns 0;
    new Doub1e(12.3).compareToCnew 0ouble(12.51)) returns -1;
  • 包装类有一个静态方法valueOf(String s) 该方法创建一个新对象,并将它初始化为指定字符串表示的值

    比如

    1
    2
    Double doubleObject-Double.valueOf("12.4") ;
    Integer integerObject = Integer.valueOf( "12")
  • 包装类都有两个重载的方法,将数值字符换转换为正确的以10(十进制)或指定值基数的数值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // These two methods are in the Byte class
    public static byte parseByte(String s)
    public static byte parseByte(String s, int radix)
    // These two methods are in the Short class
    public static short parseShort(String s)
    public static short parseShort(String s, int radix)
    // These two methods are in the Integer class
    public static int parseInt(String s)
    public static int parseInt(String s, int radix)
    // These two methods are in the Long class
    public static long parseLong(String s)
    public static long parseLong(String st int radix)
    // These two methods are in the Float class
    public static float parseFloat(String s)
    public static float parseFloat(String s, int radix)
    // These two methods are in the Double class
    public static double parseDouble(String s)
    public static double parseDouble(String s, int radix)

例如

1
2
3
4
Integer.parselnt("ll", 2)returns 3;
Integer.parselnt( "12", 8)returns 10;
Integer.parselnt("13",10)returns 13;
Integer.parselnt( "1A",16)returns 26;

注意,可以用format方法将一个十进制数转换为十六进制数
例如

1
String.format("\x", 26)returns 1A;

BigInteger和BigDecimal类

BigInteger类和BigDecimal类可以用于表示任意大小和精度的整数或者十进制数

  • 用于进行非常大的数的计算或者高精度浮点值的计算
  • 不可变
  • 构造方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    new BigInteger(String)
    new BigDecimal(String)
    - **使用`add`,`substract`,`multiple`,`divide`和`remainder`方法完成算数运算**
    >
    ```java
    BigInteger a = new BigInteger("9223372036854775807");
    BigInteger b = new BigInteger("2");
    BigInteger c = a.multiply(b); // 9223372036854775807 * 2
    System.out.println(c);
  • BigDecimal对象指定尺度舎入方式

    对 BigDecimal 对象的精度没有限制。如果结果不能终止,那么divide 方法会抛出 ArithmeticException 异常。但是,可以使用重载的divide(BigDecimal d.int scale, int roundingMode)方法来指定尺度和舍入方式来避免这个异常
    例如创建两个尺度为20,舎入方式BigDecimal.ROUND_UP的BigDecimal对象

    1
    2
    3
    4
    BigDecimal a = new BigDecimal(1.0);
    BigDecimal b = new BigDecimal(3);
    BigDecimal c = a.divide(b, 20, BigDecimal.ROUNDJJP);
    System.out.println(c);

输出为0.33333333333333333334

  • 返回任意整数阶乘的方法
    一个整数的阶乘可能会非常大,下面方法返回任意整数阶乘
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static BigInteger factorial(long n)
    {
    BigInteger res = BigInteger.ONE; //和new Biglnteger("1") 一样
    for(int i = 0; i < n; i++)
    {
    res = res.multiply(new BigInteger(i + ""));
    }
    return res;
    }

String类

String对象是不可改变的。字符串一旦创建,内容不能再改变

因为字符串在程序设计中是不可变的,但同时又会频繁地使用,所以Java虚拟机为了提高效率并节约内存,对具有相同字符序列的字符串直接量使用同一个实例。这样的实例成为interned字符串。

1
2
3
String s1 = "Welcome to Java";
String s2 = new String("Welcome to Java");
String s3 = "Welcome to Java";

这里s1 == s2(false), s1 == s3(true)

字符串的替换和分隔

  • 替换
    1
    2
    3
    4
    5
    6
    //用replacement替换所有的target,两个参数都是字符串。
    replace(CharSequence target, CharSequence replacement)
    //用replacement替换所有的regex匹配项,regex很明显是个正则表达式,replacement是字符串。
    replaceAll(String regex, String replacement)
    //基本和replaceAll相同,区别是只替换第一个匹配项。
    replaceFirst(String regex, String replacement)

原则,当字符串无法确定是否具有转义字符时,而且也不需要转义时,建议使用replace函数
否则,使用replaceAll函数
举例:

1
2
3
System.out.println("abac".replace("a", "\\a")); //\ab\ac
System.out.println("abac".replaceAll("a", "\\a")); //abac
System.out.println("abac".replaceFirst("a", "\\a")); //abac

  • 分隔
    1
    2
    3
    String[] tokens = "Java#HTML#Perl".split("#")
    for(int i = 0; i<tokens.length; i++)
    System.out.println(tokens[i]+" ");

输出:Java HTML Perl

匹配matches

正则表达式的形式进行字符串匹配

1
"java is fun".matches("java.*") return tue

字符串与数组之间的转换

字符串->字符数组

1
char[] chars = "java".toCharArray();

还可以使用getChars(int srcBegin.int srcEnd,char[]dst,int dstBegin)将下标从srcBegin到srcEnd-1的子串复制到字符数组dst中下标从dstBegin开始的位置。
例如, 下面的代码将字符串”CS3720”中下标从 2 到 6-1的子串”3720”复制到字符数组 dst 中下标 从 4 开始的位置:

1
2
char[] dst = {'J''A', 'V' , 'A', '1' , '3''0', '1'};
"CS3720".getChars(2, 6, dst, 4);

这样,dst 就变成了'{'J','A','V','A','3','7','2','0'}

字符数组->字符串valueOf(char[])

  • 例如,下面的语句使用String 构造方法由一个数组构造一个字符串: String str = new String(new char[]{'J', 'a' , 'v','a'});
  • 下面的语句使用 valueOf方法由一个数组构造一个字符串: String str = String.valueOf(new char[]{'J', 'a', 'v', 'a'});

    字符和数值->字符串

    例如

    1
    String.valueOf(5.44)

返回值是‘5’、‘.’、‘4’和‘4’构成的字符串

格式化字符串format

1
String.format(format, iteml, item2 itemfc)

StringBuilder和StringBuffer类

StringBuilder 和 StringBuffer 类似于 String 类,区别在于 String 类是不可 改变的。
可以给一个StringBuilder 或 StringBuffer 中添加、插入或追加新的内容,但是 String 对象一旦创建,它的值就确定了

  • 多任务并发访问——StrigBuffer
  • 单任务访问——StringBuilder

  • 添加append
    >

    1
    stringBuilder.append("Welcome");
  • 插入insert
    >

    1
    StringBuilder.insert(11, "HTML and ");
  • 删除delete,deleteAt
    >

    1
    2
    StringBuilder StringBuilder = new StringBuilder("Welcome to Java");
    stringBui1der.delete(8,11); //将构建器变为 Welcome ]ava。 stringBuilder.deleteCharAt(8) //将构建器变为 Welcome o ]ava。
  • 修改replace,setCharAt
    >

    1
    2
    stringBuilder.replace(11,15,"HTML");
    stringBuilder.setCharAt(0, 'w');
  • 逆序reverse

    1
    stringBuilder.reverse();
  • toString
    Write an expression that returns a string from a StringBuilder object sb.

    1
    sb.toString()

其他

  • 字符串的长度总是小于或等于构建器的容量。长度是存储在构建器中的字符串的实 际大小,而容量是构建器的当前大小。如果有更多的字符添加到字符串构建器,超出它的 容量,则构建器的容量就会自动增加。在计算机内部,字符串构建器是一个字符數组,因 此,构建器的容量就是数组的大小。如果超出构建器的容量,就用新的数组替换现有数组。新数组的大小为 2x( 之前数组的长度 +1)。
  • 可以使用 new StringBuilderCinitialCapacity)创建指定初始容量的 StringBuilder。 通过仔细选择初始容量能够使程序更有效。如果容量总是超过构建器的实际使用长度, JVM 将永远不需要为构建器重新分配内存。另一方面,如果容量过大将会浪费内存空间。 可以使用 trimToSize() 方法将容量降到实际的大小。

本章小结

1.面向过程范式重在设计方法。面向对象范式将数据和方法耦合在对象中。使用面向对象范式的软件 设计重在对象和对象上的操作。面向对象方法结合了面向过程范式的功能以及将数据和操作集成在 对象中的特点。
2.许多 Java方法要求使用对象作为参数。Java提供了一个便捷的办法,将基本数据类型合并或包装到 一个对象中(例如,包装 int 值到 Integer 类中,包装 double 值到 Double 类中)。
3.Java 可以根据上下文自动地将基本类型值转换为对应的包装对象,反之亦然。 4.BigInteger 类在计算和处理任意大小的整数方面是很有用的。BigDecimal 类可以用作计算和处理 带任意精度的浮点数。
5.String 对象是不可变的,它的内容不能改变。为了提高效率和节省内存,如果两个直接量字符串有 相同的字符序列,Java 虚拟机就将它们存储在一个对象中。这个独特的对象称为限定字符串对象。
6.正則表达式(缩写 regex) 是一个描述模板的字符串,用于匹配一系列字符串。可以通过指定一个模 板来匹配、替代或者分隔字符串。
7.StringBuilder/StringBuffer 类可以用来替代 String 类。String 对象是不可变的,但是可以 向 StringBuilder/StringBuffer 对象中添加、插人或追加新的内容。如果字符串的内容不需要 任何改变,就使用 String 类;如果可能改变的话,则使用 StringBuilder/StringBuffer 类