[关闭]
@MRsunhuimin 2019-07-25T11:45:09.000000Z 字数 4694 阅读 173

java (2019.07.25)

java基础

作者:孙慧敏

0. 包装类


    java中的数据类型int,double等不是对象,无法通过向上转型获取到Object提供的方法,而像String却可以,只因为String是一个对象而不是一个类型。基本数据类型由于这样的特性,导致无法参与转型,泛型,反射等过程。为了弥补这个缺陷,java提供了包装类。

包装类顾名思义就是将基本的数据类型以及一些辅助方法包装到类中,例如自己实现一个int的包装类:

  1. class IntDemo {
  2. private int num;
  3. public IntDemo(int num) {
  4. this.num = num;
  5. }
  6. public int intValue() {
  7. return this.num;
  8. }
  9. }

1. Java提供的包装类

    虽然上面的IntDemo类能实现一些辅助功能,而且可以支持泛型反射等功能,但是如果如果每次使用都自己封装这么一个类的话,就太繁琐了。所以,java为我们提供了基本数据类型的包装类,这些包装类分为两类,一种是对象型包装类,不继承任何其他类(Object的直接子类),另一种是数值型包装类,继承于Number类。
    Boolean和Character两个类就是正常的属性方法封装,但是数值型的包装类继承了一个Number类。
    其实Number中定义的方法就是用于拆箱装箱的。

2. 拆箱与装箱

    装箱:
        将基本数据类型封装为包装类对象,利用每一个包装类提供的构造方法实现装箱操作。
    拆箱:
        将包装类中包装的基本数据类型数据取出。
  1. // 装箱
  2. Integer integer1 = new Integer(1);
  3. // 拆箱
  4. int integer2 = integer1.intValue();

JDK1.5之后提供自动拆装箱。

  1. // 自动装箱
  2. Integer integer1 = 1;
  3. // 自动拆箱
  4. int integer2 = integer1;

包装类的特点:

1. JDK1.5后,允许基本数据类型和包装类型进行混合数学运算
2. 包装类并不是用来取代基本数据类型的
3. 在基本数据类型需要用对象表示时使用

3. 自动装箱的内存复用

    自动装箱时,对于Integer var = ?,如果var指向的对象在-128 至 127 范围内的赋值时,生成的Integer实例化对象是由IntegerCache.cache() 方法产生,它会复用已有对象。和String的共享池操作是一个道理,cache()方法会将位于-128~127范围内产生的Integer对象入池,下次使用的时候,从池中拿去,就不会在创建了。
    所以,在这个数值区间内的 Integer对象的栈指向(属性名) 可以直接使用==进行判断,因为值相同,指向的就是同一片区域。但是这个区间之外的所有数据,自动装箱都会在堆上产生实例化,并不再复用已有对象,这是一个大坑,为了避免这个问题,推荐使用 equals 方法进行Integer的判断。
    对于所有数值型的包装类来说,都会涉及到上面这种问题,一定要多加注意。
    而对于手动装箱,即采用new进行包装类创建时,不会发生内存复用,因为new关键字每次使用,都会开辟新的空间,这和String采用构造方法创建字符串不入池相对应。

4. 包装类编码规约

    所有的相同类型的包装类对象之间值的比较,全部使用equals()方法。
    所有的POJO(简单Java类,只包含基本属性,有参构造,get/set)类属性必须使用包装类数据类型,类属性即static属性。
    RPC(远程方法调用)方法返回值和参数必须使用包装数据类型。
    推荐所有的局部变量使用基本数据类型。

5. 包装类对字符串与基本数据类型转换的支持

    实际工程中,各种数据的接收是通常是通过字符串完成的,所以要掌握包装类对字符串转换的方法。
  1. // String->int
  2. public static int parselnt(String s)throws NumberFormatException;
  3. // String->double
  4. public static double parseDouble(String)throws NumberFormatException;
  5. // String->Boolean
  6. public static boolean parseBoolean(String s)

注意

    字符串转数值类型时字符串只能包含数字,否则会抛出 NumberFormatException 异常,这是一个非受查异常。

    但是字符串转Boolean是个特例,parseBoolean()方法会将”true”转为true,而将非”true”的字符串转为false。

6. 包装类的构造方法

所有包装类都可将与之对应的基本数据类型作为参数,来构造它们的实例

    public Type(type value)
        如:Integer i=new Integer(1);

除Character类外,其他包装类可将一个字符串作为参数构造它们的实例

    public Type(String value)
        如:Integer i=new Integer("123");

注意事项

    当Number包装类构造方法参数为String类型时,字符串不能为null,且该字符串必须可解析为相应的基本数据类型的数据,否则编译不通过,运行时会抛出NumberFormatException异常

    Boolean类构造方法参数为String类型时,若该字符串内容为"true"(不考虑大小写),则该Boolean对象表示true,否则表示false。

7. 包装类常用方法

1. XXXValue():包装类转换成基本类型

    byteValue()、intValue()
    longValue()、shortValue()
    doubleValue()、floatValue()
    charValue()、booleanValue()
  1. Integer integerId=new Integer(25);
  2. int intId=integerId.intValue();

2. toString():以字符串形式返回包装对象表示的基本类型数据(基本类型->字符串)

  1. String sex=Character.toString('男');
  2. String id=Integer.toString(25);
  3. String sex='男'+"";
  4. String id=25+"";

3. parseXXX():把字符串转换为相应的基本数据类型数据(Character除外)(字符串->基本类型)

  1. int num=Integer.parseInt("36");
  2. boolean bool=Boolean.parseBoolean("false");
  3. //public static type parseType(String type)

4. valueOf()

  1. //所有包装类都有如下方法(基本类型->包装类)
  2. public static.Type valueOf(type value)
  3. 如:
  4. Integer intValue = Integer.valueOf(21);
  5. //除Character类外,其他包装类都有如下方法(字符串->包装类)
  6. public static.Type valueOf(String.s)
  7. 如:
  8. Integer intValue = Integer.valueOf("21");

8. Math类

    java.lang.Math类提供了常用的数学运算方法和两个静态常量E(自然对数的底数) 和PI(圆周率)
  1. Math.abs(-3.5); //返回3.5
  2. Math.max(2.5, 90.5);//返回90.5
  3. int random = (int) (Math.random() * 10); //生成一个0-9之间的随机数

9. Random类

生成随机数的其他方式

    java.util.Random类 
  1. Random rand=new Random(); //创建一个Random对象
  2. for(int i=0;i<20;i++){//随机生成20个随机整数,并显示
  3. int num=rand.nextInt(10);//返回下一个伪随机数,整型的
  4. System.out.println("第"+(i+1)+"个随机数是:"+num);
  5. }
用同一个种子值来初始化两个Random对象,然后用每个对象调用相同的方法,得到的随机数也是相同的

10. String类

String类位于java.lang包中,具有丰富的方法
如:计算字符串的长度、比较字符串、连接字符串、提取字符串

使用String对象存储字符串
    String s = "Hello World";
    String s = new String();
    String s = new String("Hello World");

10.1 length()方法

    String类提供了length()方法,确定字符串的长度

10.2 equals()方法

    String类提供了equals()方法,比较存储在两个字符串对象的内容是否一致

equals()方法比较原理:
    equals():检查组成字符串内容的字符是否完全一致

“==”和equals()有什么区别呢?
    ==:判断两个字符串在内存中的地址,即判断是否是同一个字符串对象

10.3 补充-字符串比较的其他方法

  1. equalsIgnoreCase()方法

        String.equals()对大小写敏感,而String.equalsIgnoreCase()忽略大小写 例如:"ABC".equals("abc")是false;"ABC".equalsIgnoreCase("abc")为ture
    
  2. toLowerCase()方法

        将所有的英文字符转换为小写字母
    
  3. toUpperCase()方法

        将所有的英文字符转换为大写字母
    

    注意:这两个方法只对英文字母有效,对除了A~Z和a~z的其余字符不会产生影响。

10.4 字符串连接

方法1:使用“+”
方法2:使用String类的concat()方法

  1. public static void main(String[] args) {
  2. // example1
  3. String str1 = "s1";
  4. System.out.println(str1 + 100);//s1100
  5. System.out.println(100 + str1);//100s1
  6. String str2 = "s2";
  7. str2 = str2.concat("a").concat("bc");
  8. System.out.println(str2);//s2abc
  9. // example2
  10. String str3 = "s3";
  11. System.out.println(str3 + null);//s3null
  12. System.out.println(null + str3);//nulls3
  13. String str4 = null;
  14. System.out.println(str4.concat("a"));//NullPointerException
  15. System.out.println("a".concat(str4));//NullPointerException
  16. }

两者的区别如下:

1. +可以是字符串或者数字及其他基本类型数据,而concat只能接收字符串。

2. +左右可以为null,concat会为空指针。

3. 如果拼接空字符串,concat会稍快,在速度上两者可以忽略不计,如果拼接更多字符串建议用StringBuilder。

4. 从字节码来看+号编译后就是使用了StringBuiler来拼接,所以一行+++的语句就会创建一个StringBuilder,多条+++语句就会创建多个,所以为什么建议用StringBuilder的原因。(String,StringBuilder,StringBuffer三者的区别见《扩展知识点》)
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注