第二十章 常用类

1 字符串String

1.1 字符串的存储原理

User.java

package com.bjpowernode.javase.string;

public class User {
   private int id;
   private String name;

   public User() {
  }

   public User(int id, String name) {
       this.id = id;
       this.name = name;
  }

   public int getId() {
       return id;
  }

   public void setId(int id) {
       this.id = id;
  }

   public String getName() {
       return name;
  }

   public void setName(String name) {
       this.name = name;
  }
}

UserTest.java


public class UserTest {
   public static void main(String[] args) {
       User user = new User(111, "xiaohong");
  }
}

 

 

 

 

StringTest01.java

关于Java JDK中内置的一个类:java.lang.String
   1、String表示字符串类型,属于引用数组类型,不属于基本数据类型。
   
   2、在java中使用双引号括起来的都是String对象。例如:"abc", "def", "a", 这是三个String对象
   
   3、java中规定,双引号括起来的字符串,是不可变的,也就是说“abc”自出生到最终死亡,不可变,不能变成“abcd”,也不能变成“ab”
   
   4、在JDK当中双引号括起来的字符串,例如:"abc", "def"都是直接存储在“方法区”的“字符串常量池”当中。
       为什么SUN公司把字符中存储在一个“字符串常量池”当中呢?因为字符串在实际的开发中使用的太频繁,为了执行效率,把字符串放到了方法区的字符串常量池当中。


public class StringTest01 {
   public static void main(String[] args) {
       // 这两行代码表示底层创建了3个字符串对象,都在字符串常量池当中。
       String s1 = "abcdef";
       String s2 = "abcdef" + "xy";

       // 分析:这是使用new的方式创建的字符串对象,这个代码中的“xy”是从哪里来的?
       // 凡是双引号括起来的都在字符串常量池中有一份。
       // new对象的时候一定在堆内存中开辟空间
       String s3 = new String("xy");

       // i变量中保存的是100这个值。
       int i = 100;
       // s变量中保存的是字符串对象的内存地址
       // s引用中保存的不是"abc"
       // 而0x1111是"abc"字符串对象在字符串常量池当中的内存地址
  }
}

 

 

 

StringTest02.java

package com.bjpowernode.javase.string;

import java.sql.SQLOutput;

public class StringTest02 {
   public static void main(String[] args) {
       String s1 = "hello";
       // "hello"是存储在方法区的字符串常量池当中
       // 所以这个"hello"不会新建。(因为这个对象已经存在了)
       String s2 = "hello";
       // 分析结果是true还是false?
       // == 双等号比较的是不是变量中保存的内存地址?是的。
       System.out.println(s1 == s2);  // true

       String x = new String("xyz");
       String y = new String("xyz");
       // 分析结果是true还是false?
       // == 双等号比较的是不是变量中保存的内存地址?是的。
       System.out.println(x == y);  // false

       // 通过这个案例的学习,我们知道了,字符串对象之间的比较不能使用“==”
       // “==”不保险,应该调用String类的equals方法。
       // String类已经重写了equals方法,以下的equals方法调用的是String重写之后的equals
       System.out.println(x.equals(y));  // true

       String k = new String("testString");
       // String k = null;
       // "testString"是一个String字符串对象。只要是对象都能调用方法。
       System.out.println("testString".equals(k));  // 建议使用这种方式,因为这个可以避免空指针异常
       System.out.println(k.equals("testString"));  // 存在空指针异常的风险,不建议这样写。
  }
}

 

 

 

StringTest03.java

package com.bjpowernode.javase.string;

/*
分析以下程序,一共创建了几个对象
*/

public class StringTest03 {
   public static void main(String[] args) {
       /*
       一共3个对象:
           方法区字符串常量池中有1个: "hello"
           堆内存当中有两个String对象。
           一共3个。
        */
       String s1 = new String("hello");
       String s2 = new String("hello");
  }
}

 

1.2 String类的构造方法

第一个:String s = new String("")
第二个:String s = ""; 最常用
第三个:String s = new String(char数组);
第四个:String s = new String(char数组, 起始下标, 长度);
第五个:String s = new String(byte数组);
第六个:String s = new String(byte数组, 起始下标, 长度);

                         
public class StringTest04 {
   public static void main(String[] args) {

       // 创建字符串对象最常用的一种方式
       String s1 = "hello world";
       // s1这个变量中保存的是一个内存地址
       // 按说以下应该输出一个地址
       // 但是输出一个字符串,说明String类已经重写了toString()方法
       System.out.println(s1);  // hello world
       System.out.println(s1.toString());  // hello world

       // 这里只掌握常用的构造方法。
       byte[] bytes = {97, 98, 99};  // 97是a,98是b,99是c
       String s2 = new String(bytes);
       // 输出一个引用的时候,会自动调用toString()方法,默认Object的话,会默认输出内存地址。
       // 通过输出结果我们得出一个结论:String类已经重写了toString()方法
       // 输出字符串对象的话,输出的不是对象的内存地址,而是字符串本身
       System.out.println(s2);  // abc

       // String(字节数组,数组元素下标的起始位置,长度)
       // 将byte数组中的一部分转换成字符串
       String s3 = new String(bytes, 1, 2);
       System.out.println(s3);

       // 将char数组全部转换成字符串
       char[] chars = {'我', '是', '中', '国', '人'};
       String s4 = new String(chars);
       System.out.println(s4);
       // 将char数组的一部分转换成字符串
       String s5 = new String(chars, 2, 3);
       System.out.println(s5);

       String s6 = new String("helloworld");
       System.out.println(s6);
  }
}
                         

 

1.3 String常用方法

package com.bjpowernode.javase.string;

public class StringTest05 {
   public static void main(String[] args) {
       // String类当中常用方法
       // 1(掌握). char charAt(int index)
       char c = "中国人".charAt(1);  // "中国人"是一个字符串String对象,只要是对象就能“点”
       System.out.println(c);

       // 2(了解).int compareTo(String anotherString)
       // 字符串之间比较大小不能直接使用 > <,需要使用compareTo方法
       int result = "abc".compareTo("abc");
       System.out.println(result);  // 0(等于0) 前后一致

       int result2 = "abcd".compareTo("abce");
       System.out.println(result2);  // -1(小于0) 前小后大

       int result3 = "abce".compareTo("abcd");
       System.out.println(result3);  // 1(大于0) 前大后小

       // 拿着字符串第一个字母和后面字符串的第一个字母比较,能分胜负就不比较了。
       System.out.println("xyz".compareTo("yxz"));  // -1

       // 3(掌握). boolean contains(CharSequence s)
       // 判断前面的字符串中是否包含后面的子字符串
       System.out.println("helloWorld.java".contains(".java"));  // true
       System.out.println("http://www.baidu.com".contains("https://"));  // false

       // 4(掌握). boolean endsWith(String suffix)
       System.out.println("test.txt".endsWith(".java"));  // false
       System.out.println("test.txt".endsWith(".txt"));  // true
       System.out.println("fdsjkfaj;sdfjaksdfkjasd;fjasdk;fjkasdff".endsWith("ff"));  // true

       // 5(掌握). boolean equals(Object anObject)
       // 比较两个字符串必须使用equals方法,不能使用"=="
       // equals方法有没有调用compareTo方法?JDK13中并没有调用compareTo方法

       // 6(掌握). boolean equalsIgnoreCase(String anotherString)
       // 判断两个字符串是否相等,并且同时忽略大小写
       System.out.println("AbC".equalsIgnoreCase("abC"));

       // 7(掌握). byte[] getBytes()
       // 将字符串对象转换成字节数组
       byte[] bytes = "abcdef".getBytes();
       for(int i = 0; i < bytes.length; i++){
           System.out.println(bytes[i]);
      }

       // 8(掌握). int indexOf(String str)
       // 判断某个子字符串在当前字符串中第一次出现处的索引。
       System.out.println("oraclejavac++.netc#pythonphpjavaoraclec++".indexOf("java")); // 6

       // 9(掌握). boolean isEmpty()
       // 判断某个字符串是否为“空字符串”,底层源代码调用的应该是字符串的length()方法。
       String s = "";
       System.out.println(s.isEmpty());
       String s1 = "1";
       System.out.println(s1.isEmpty());

       // 10(掌握). int length();
       // 面试题:判断数组长度和判断字符串长度不一样
       // 判断数组长度是length属性,判断字符串长度是length()方法
       System.out.println("abc".length());

       // 11(掌握). int lastIndexOf(String str)
       // 判断某个子字符串在当前字符串中最后一次出现的索引(下标)
       System.out.println("oraclejavac++javac#phpjavapython".lastIndexOf("java"));  // 22

       // 12(掌握). String replace(CharSequence target, CharSequence replacement)
       // 替换
       // String的父接口就是:CharSequence
       String newString = "http://www.baidu.com".replace("http://", "https://");
       System.out.println(newString);
       // 把以下字符串中的“=”替换成“:”
       String newString2 = "name=zhangsan&password=123&age=20".replace("=", ":");
       System.out.println(newString2);  // name:zhangsan&password:123&age:20

       // 13(掌握). String[] split(String regex)
       // 拆分字符串
       String[] ymd = "1980-10-11".split("-");  // "1980-10-11" 按照 "="分隔符进行拆分
       for(int i = 0; i < ymd.length; i++){
           System.out.println(ymd[i]);
      }
       String param = "name=xiaohong&passowrd=123&age=18";
       String[] params = param.split("&");
       System.out.println(params);
       for(int i = 0; i < params.length; i++){
           System.out.println(params[i]);
      }

       // 14(掌握). boolean startsWith(String prefix)
       // 判断某个字符串是否以某个子字符串开始
       System.out.println("http://www.baidu.com".startsWith("http"));
       System.out.println("http://www.baidu.com".startsWith("https"));

       // 15(掌握). String substring(int beginIndex) 参数是起始下标
       // 截取字符串
       System.out.println("http://www.baidu.com".substring(7));  // www.baidu.com

       // 16(掌握). String substring(int beginIndex, int endIndex)
       // 左闭右开
       System.out.println("http://www.baidu.com".substring(7, 10));  // www

       // 17(掌握). char[] toCharArray()
       // 将字符串转换成char数组
       char[] chars = "我是中国人".toCharArray();
       for(int i = 0; i < chars.length; i++){
           System.out.println(chars[i]);
      }

       // 18(掌握). String toLowerCase()
       // 转换为小写
       System.out.println("AJDKFKJSDKJjfdksfDJ".toLowerCase());

       // 19(掌握). String toUpperCase()
       // 转换成大写
       System.out.println("AJDKFKJSDKJjfdksfDJ".toUpperCase());

       // 20(掌握). String trim();
       // 去除字符串前后空白
       System.out.println("     hello   world     ".trim());

       // 21(掌握). String中只有一个方法是静态的,不需要new对象
       // 这个方法叫做valueOf()
       // 作用:将“非字符串”转换成“字符串”
       // String ss = String.valueOf(true);
       // System.out.println(ss); // true
       // String ss2 = String.valueOf(100);
       // String ss3 = String.valueOf(3.14);
       // System.out.println(ss2);
       // System.out.println(ss3);

       // 这个静态的valueOf()方法,参数是一个对象的时候, 会自动调用该对象的toString()方法吗?
       String sss1 = String.valueOf(new Customer());
       // System.out.println(sss1); // 没有重写toString()方法之前是对象内存地址:com.bjpowernode.javase.string.Customer@16b98e56
       System.out.println(sss1);  // 重写toString()方法之后输出:我是一个Vip客户!

       // 我们是不是可以研究一下println()方法的源代码了?
       System.out.println(100);
       System.out.println(3.14);
       System.out.println(true);
       System.out.println(new Object());

       Object obj = new Object();
       // 通过源代码可以看出:为什么输出一个引用的时候,会调用toString()方法
       // 本质上System.out.println()这个方法在输出任何数据的时候都是先转换成字符串,再输出
       System.out.println(obj);
  }
}

class Customer{
   @Override
   public String toString() {
       return "我是一个Vip客户!";
  }
}

 

 

2 StringBuffer

2.1 StringBuffer进行字符串拼接

StringBufferTest01.java

package com.bjpowernode.javase.stringbuffer;

/*
思考:我们在实际的开发中,如果需要进行字符串的频繁拼接,会有什么问题?
   因为java中的字符串是不可变的,每一次拼接都会产生新字符串
   这样会占用大量的方法区内存,造成内存空间的浪费。
       String s = "abc";
       s += "hello";
       就以上两行代码,就导致在方法区字符串常量池当中创建了3个对象:
           "abc"
           "hello"
           "abchello"
*/

public class StringBufferTest01 {
   public static void main(String[] args) {
       String s = "";
       // 这样做会给java的方法区字符串常量池带来很大的压力
       for(int i = 0; i < 100; i++){
           s += i;
           System.out.println(s);
      }
  }
}

StringBufferTest02.java

package com.bjpowernode.javase.stringbuffer;

/*
如果以后需要进行大量字符串的拼接操作,建议使用JDK中自带的
   java.lang.StringBuffer
   java.lang.StringBuilder

如何优化StringBuffer的性能?
   在创建StringBuffer的时候尽可能给定一个初始化容量
   最好减少底层数组的扩容次数,预估计一下,给一个大一些的初始化容量
*/

public class StringBufferTest02 {
   public static void main(String[] args) {

       // 创建一个初始化容量为16个byte[] 数组。(字符串缓冲区对象)
       StringBuffer stringBuffer = new StringBuffer();

       // 拼接字符串,以后拼接字符串统一调用append()方法
       // append是追加的意思。
       stringBuffer.append("a");
       stringBuffer.append("b");
       stringBuffer.append("d");
       stringBuffer.append(3.14);
       stringBuffer.append(true);
       stringBuffer.append(100L);
       // append方法底层在进行追加的时候,如果byte数组满了,会自动扩容。

       System.out.println(stringBuffer);

       // 指定初始化容量的StringBuffer对象(字符串缓冲区对象)
       StringBuffer sb = new StringBuffer(100);
       sb.append("hello");
       sb.append("world");
       sb.append("hello");
       System.out.println(sb);
  }
}

 

2.2 StringBuffer和StringBuilder的区别?

package com.bjpowernode.javase.stringbuffer;

/*
java.lang.StringBuilder
StringBuffer和StringBuilder的区别?
   StringBuffer中的方法都有: synchronized关键字修饰,表示StringBuffer在多线程环境下运行是安全的。
   StringBuilder中的方法都没有:synchronized关键字修饰,表示StringBuilder在多线程环境下运行是不安全的。

   StringBuffer是线程安全的
   StringBuilder是非线程安全的
*/

public class StringbuilderTest01 {
   public static void main(String[] args) {

       // 使用StringBuilder也是可以完成字符串的拼接
       StringBuilder sb = new StringBuilder();
       sb.append(100);
       sb.append(true);
       sb.append("hello");
       sb.append("xiaohong");
       System.out.println(sb);
  }
}

 

 

3 基础类型对应的8个包装类

3.1 包装类存在的意义

IntegerTest01.java

package com.bjpowernode.javase.integer;

/*
1、java中为8种基本数据类型又对应准备了8种包装类型。8种包装类属于引用类型,父类是Object类。

2、思考:为什么要再提供8种包装类呢?
   因为8种基本数据类型不够用。
   所以SUN又提供对应的8种包装类型
*/

public class IntegerTest01 {
   public static void main(String[] args) {
       // 有没有这种需求:调用doSome()方法的时候需要传一个数字进去。
       // 但是数字属于基本数据类型,而doSome()方法参数的类型是Object
       // 可见doSome()方法无法接收基本数据类型的数字,那怎么办呢?可以传一个数字对应的包装类进去。

       // 把100这个数字经过构造方法包装成对象。
       MyInt myInt = new MyInt(100);
       // doSome()方法虽然不能直接传100,但是可以传一个100对应的包装类型。
       doSome(myInt);
  }

   public static void doSome(Object obj){
       // System.out.println(obj); // com.bjpowernode.javase.integer.MyInt@2d98a335
       System.out.println(obj);
  }
}

MyInt.java

package com.bjpowernode.javase.integer;

/*
这种包装类目前是我自己写的,实际开发中我们不需要自动写。
8种基本数据类型对应的8种包装类,SUN公司已经写好了,我们直接用。
*/

public class MyInt {
   int value;

   public MyInt() {
  }

   public MyInt(int value) {
       this.value = value;
  }

   @Override
   public String toString() {
       return String.valueOf(value);
  }
}

 

3.2 八种包装类以及装箱和拆箱

8种基本数据类型对应的包装类型名是什么?
   基本数据类型              包装类型
   ---------------------------------------
   byte                      java.lang.Byte (父类Number)
   short                     java.lang.Short (父类是Number)
   int                       java.lang.Integer (父类是Number)
   long                      java.lang.Long (父类是Number)
   float                     java.lang.Float (父类是Number)
   double                    java.lang.Double (父类是Number)
   boolean                   java.long.Boolean (父类是Object)
   char                      java.lang.Character (父类是Object)

2、以上几种包装类中,重点以java.lang.Integer为代表进行学习,其它的类型照葫芦画飘就行

3、几种包装类中其中6种都是数字对应的包装类,他们的父类都是Number,可以先研究一下Number公共的方法
   Number是一个抽象类,无法实例化对象
   Number类中有这样的方法:
       byte byteValue()  返回byte类型的数值
       abstract double doubleValue()   返回double类型的数值
       abstract float floatValue()    返回float类型的数值
       abstract int intValue()    返回int类型的数值
       abstract long longValue()    返回long类型数值
       short shortValue()    返回short类型的数值
       这些方法其实所有的数字包装类的子类都有,这些方法是负责拆箱的。


package com.bjpowernode.javase.integer;

public class IntegerTest02 {
   public static void main(String[] args) {
       // 123这个基本数据类型,进行构造方法的包装达到了:基本数据类型向引用数据类型的转换。
       // 基本数据类型 --(转换)--> 引用数据类型 (装箱)
       Integer i = new Integer(123);

       // 将引用数据类型转 --(转换)--> 基本数据类型 (拆箱)
       float f = i.floatValue();
       System.out.println(f);

       // 将引用数据类型 --(转换)--> 基本数据类型
       int retValue = i.intValue();
       System.out.println(retValue);
  }
}

 

3.3 Integer的构造方法

package com.bjpowernode.javase.integer;

/*
关于Integer类的构造方法,有两个:
   Integer(int);
   Integer(String);
*/

public class IntegerTest03 {
   public static void main(String[] args) {

       // Java9之后不建议使用这个构造方法了。
       // 将数字100转换成Integer包装类型(int --> Integer)
       Integer x = new Integer(100);
       System.out.println(x);

       // 将String类型的数字,转换成Integer包装类型 (String --> Integer)
       Integer y = new Integer("123");
       System.out.println(y);
  }
}

 

3.4 通过常量获取最大值和最小值

package com.bjpowernode.javase.integer;

public class IntegerTest04 {
   public static void main(String[] args) {
       // 通过访问包装类的常量,来获取最大值和最小值
       System.out.println("int的最大值" + Integer.MAX_VALUE);
       System.out.println("int的最小值" + Integer.MIN_VALUE);
       System.out.println("byte的最大值" + Byte.MAX_VALUE);
       System.out.println("byte的最小值" + Byte.MIN_VALUE);
  }
}
 
 

3.5 StringBuffer和StringBuilder补充

1、面试题:String为什么是不可变的?
   我看到源代码,String类中有一个byte[]数组,这个byte[]数组采用了final修饰,
   因为数组一旦创建长度不可变,并且被final修饰的引用一旦指向某个对象之后,不可再指向其它对象
   所以String是不可变的。
       "abc" 无法变成 "abcd"

2、StringBuilder/StringBuffer为什么是可变的呢?
   我看到源代码,StringBuffer/StringBuilder内部实际上是一个byte[]数组,
   这个byte[]数组没有被final修饰,StringBuffer/StringBuilder的初始化
   容量我记得应该是16,当存满之后会进行扩容,底层调用了数组拷贝的方法
   System.arraycopy()...是这样扩容的。所以StringBuffer/StringBuilder
   适合于字符串的频繁拼接操作。


package com.bjpowernode.javase.stringbuffer;

public class StringBufferTest04 {
   public static void main(String[] args) {

       // 字符串不可变是什么意思?
       // 是说双引号里面的字符串对象一旦创建不可变
       String s = "abc";  // "abc"放到了字符串常量池当中,"abc"不可变

       // s变量是可以指向其它对象的
       // 字符串不可变不是说以上变量s不可变,说的是"abc"这个对象不可变
       s = "abc";  // "xyz"放到了字符串常量池当中,"xyz"不可变
  }
}

 

3.6 自动装箱和自动拆箱

IntegerTest05.java

package com.bjpowernode.javase.integer;

/*
在JDK1.5之后,支持自动拆箱和自动装箱了
   自动装箱:基本数据类型自动转换成包装类
   自动拆箱:包装类自动转换成基本数据类型

有了自动拆箱之后,Number类中的方法就用不着了!

自动装箱和自动拆箱的好处?
   方便编程
*/

public class package com.bjpowernode.javase.integer;

/*
在JDK1.5之后,支持自动拆箱和自动装箱了
   自动装箱:基本数据类型自动转换成包装类
   自动拆箱:包装类自动转换成基本数据类型

有了自动拆箱之后,Number类中的方法就用不着了!

自动装箱和自动拆箱的好处?
   方便编程
*/

public class IntegerTest05 {
   public static void main(String[] args) {
       // 自动装箱
       // int类型 --(自动转换为)--> Integer
       // 900是基本数据类型
       // x是包装类型
       Integer x = 900;
       System.out.println(x);

       // 自动拆箱
       // Integer类型 --(自动转换为)--> int类型
       // x是包装类型
       // y是基本类型
       int y = x;
       System.out.println(y);

       // z是一个引用,z是一个变量,z还是保存了一个对象的内存地址。
       Integer z = 1000;  // 等同于: Integer z = new Integer(1000);
       // 分析为什么这个没有报错呢?
       // + 两边要求基本数据类型的数字,z是包装类,不属于数据类型,这里会对进行自动拆箱,将z转换成基本数据类型
       System.out.println(z + 1);

       Integer b = 1000;  // Integer a = new Integer(1000); a是个引用,保存内存地址指向对象
       Integer a = 1000;  // Integer b = new Integer(1000); b是个引用,保存内存地址指向对象
       // == 比较的是对象的内存地址,a和b两个引用中保存的对象内存地址不同。
       // == 这个运算符不会触发拆箱机制,(只有+ - * /等运算符的时候才会)
       System.out.println(a == b);


  }
}
{
   public static void main(String[] args) {
       // 自动装箱
       // int类型 --(自动转换为)--> Integer
       // 900是基本数据类型
       // x是包装类型
       Integer x = 900;
       System.out.println(x);

       // 自动拆箱
       // Integer类型 --(自动转换为)--> int类型
       // x是包装类型
       // y是基本类型
       int y = x;
       System.out.println(y);

       // z是一个引用,z是一个变量,z还是保存了一个对象的内存地址。
       Integer z = 1000;  // 等同于: Integer z = new Integer(1000);
       // 分析为什么这个没有报错呢?
       // + 两边要求基本数据类型的数字,z是包装类,不属于数据类型,这里会对进行自动拆箱,将z转换成基本数据类型
       System.out.println(z + 1);

       Integer b = 1000;  // Integer a = new Integer(1000); a是个引用,保存内存地址指向对象
       Integer a = 1000;  // Integer b = new Integer(1000); b是个引用,保存内存地址指向对象
       // == 比较的是对象的内存地址,a和b两个引用中保存的对象内存地址不同。
       // == 这个运算符不会触发拆箱机制,(只有+ - * /等运算符的时候才会)
       System.out.println(a == b);


  }
}

IntegerTest06.java

package com.bjpowernode.javase.integer;

/*
这个题目是Integer非常重要的面试题。
*/

public class IntegerTest06 {
   public static void main(String[] args) {
       Integer a = 128;
       Integer b = 128;
       System.out.println(a == b);  // false

       /*
       java中为了提高程序的执行效率,将[-128 ~ 127]之间所有的包装对象提前创建好,
       放到了一个方法区“整数型常量池”当中了,目的是只要用这个区间的数据不需要再new了,
       直接从整数型常量池当中取出来

       原理:x变量中保存的对象的内存地址和y中保存的对象的内存地址是一样的。
        */
       Integer x = 127;
       Integer y = 127;
       // == 永远判断的是两个对象的内存地址是否相同
       System.out.println(x == y);  // true
  }
}

 

 

 

3.7 Integer常用方法

IntegerTest07.java

package com.bjpowernode.javase.integer;

/*
总结一下之前所学的经典异常
   空指针异常:NullPointerException
   类型转换异常:ClassCaseException
   数组下标越界异常:ArrayIndexOutOfBoundsException
   数字格式化异常:NumberFormatException

Integer类当中有哪些常用的方法呢?
*/

public class IntegerTest07 {
   public static void main(String[] args) {
       // 手动装箱
       Integer x = new Integer(1000);


       // 手动拆箱
       int y = x.intValue();
       System.out.println(y);

       // 编译的时候没问题,一切符合java语法,运行会不会出现问题呢?
       // 不是一个“数字”可以包装成Integer吗?不能。运行时出现异常
       // java.lang.NumberFormatException
       // Integer a = new Integer("中文");

       // 重点方法
       // static int parseInt(String s);
       // 静态方法,传参String,返回int
       int retValue = Integer.parseInt("123");  // String --(转换)--> int
       // int retValue2 = Integer.parseInt("中文"); // NumberFormatException
       System.out.println(retValue + 100);  // 223

       // 照葫芦画瓢
       double retValue3 = Double.parseDouble("3.14");
       System.out.println(retValue3 + 1);  // 4.140000000000001(精度问题)

       float retValue4 = Float.parseFloat("1.0");
       System.out.println(retValue4 + 1);  // 2.0

       // ----------------------以下内容作了了解--------------------
       // static String toBinaryString(int i);
       // 静态的:将十进制转换成二进制字符串
       String binaryString = Integer.toBinaryString(3);
       System.out.println(binaryString);  // "11" 二进制字符串

       // static String toHexString(int i)
       // 静态的:将十进制转换成十六进制字符串
       // 十六进制:1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a
       String hexString = Integer.toHexString(16);
       String hexString2 = Integer.toHexString(17);
       System.out.println(hexString);  // "10"
       System.out.println(hexString2);  // "11"

       // static String toOctalString(int i)
       // 静态的:将十进制转换成十六进制字符串。
       String octalString = Integer.toOctalString(8);
       System.out.println(octalString);  // "10"

       System.out.println(new Object());  // java.lang.Object@5f184fc6

       // valueOf方法作为了解
       // static Integer valueOf(int i)
       // 静态的:int --> Integer
       Integer i1 = Integer.valueOf(100);
       System.out.println(i1);

       // static Integer valueOf(String s)
       // 静态的:String --> Integer
       Integer i2 = Integer.valueOf("1000");
       System.out.println(i2);

       int i = 102;
       String s1 = i + "";
       System.out.println(s1);
       String s2 = String.valueOf(i);
       System.out.println(s2);
  }
}

IntegerTest08.java

package com.bjpowernode.javase.integer;

/*
String int Integer之间互相转换
*/

public class IntegerTest08 {
   public static void main(String[] args) {

       // String --> int
       String s1 = "100";
       int i1 = Integer.parseInt(s1);
       System.out.println(i1 + 1);  // 101
       // int --> String
       String s2 = i1 + "";
       System.out.println(s2 + 1);  // 1001

       // int --> Integer
       // 自动装箱
       Integer x = 1000;
       // Integer --> int
       // 自动拆箱
       int y = x;

       // String --> Integer
       Integer k = Integer.valueOf("123");
       System.out.println(k);
       // Integer --> String
       String e = String.valueOf(k);
  }
}

 

 

 

4 日期类

4.1 java对日期的处理

package com.bjpowernode.javase.date;

/*
java中对日期的处理
   这个案例最主要掌握:
       知识点1:怎么获取系统当前时间
       知识点2:String ---> Date
       知识点3:Date ---> String
*/

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTest01 {
   public static void main(String[] args) throws Exception {

       // 获取系统当前时间(精确到毫秒的系统时间)
       // 直接调用无参数构造方法就行
       Date nowTime = new Date();

       // java.util.Date类的toString()方法已经被重写了。
       // 输出的应该不是一个对象的内存地址,应该是一个日期字符串。
       // System.out.println(nowTime);

       // 日期可以格式化吗?
       // 将日期类型Date,按照指定的格式进行转换:Date --转换成具有一定格式的日期字符串--> String
       // SimpleDateFormat是java.text包下的。专门负责日期格式化的。
       /*
       yyyy 年(年是4位)
       mm 月(月是2位)
       dd 日(日是2位)
       HH 时
       mm 分
       ss 秒
       SSS 毫秒(毫秒32位:最高999,1000毫秒代表1秒)
       注意:在日期格式中,除了y M d H m s S这些字符不能随便写之外,剩下的符号格式自己随意组织。
        */
       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:dd:ss SSS");
       String nowTimeStr = sdf.format(nowTime);
       System.out.println(nowTimeStr);


       // 假设现在有一个日期字符串String,怎么转换成Date类型?
       String time = "2008-08-08 08:08:08 888";
       // 注意:字符串的日期格式和SimpleDateFormat对象指定的日期格式要一致。不然会抛出异常:java.text.ParseException
       SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
       Date dateTime = sdf2.parse(time);
       System.out.println(dateTime);  // Fri Aug 08 08:08:08 CST 2008
  }
}

 

4.2 统计方法执行时长

package com.bjpowernode.javase.date;

/*
获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数
1秒 = 1000毫秒

简单总结一下System类的相关属性和方法:
   System.out 【out是System类的静态变量】
   System.out.println() 【println()方法不是System类的,是PrintStream类的方法】
   System.gc() 【建议启动垃圾回收器】
   System.currentTimeMillis() 获取自1970年1月1日到系统当前时间的总毫秒数
*/

public class DateTest02 {
   public static void main(String[] args) {
       long nowTimeMillis = System.currentTimeMillis();
       System.out.println(nowTimeMillis);  // 1658316580136

       // 统计一个方法耗时
       // 在调用目标方法之前记录一个毫秒数
       long begin = System.currentTimeMillis();
       print();
       // 在执行完目标方法之后记录一个毫秒数
       long end = System.currentTimeMillis();
       System.out.println("耗费时长"+ (end - begin)+"毫秒");
  }

   // 需求:统计一个方法执行所耗费的时长
   public static void print(){
       for(int i = 0; i < 1000000000; i++){
           // System.out.println("i = " + i );
      }
  }
}

 

4.3 通过毫秒构造Date对象

package com.bjpowernode.javase.date;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTest03 {
   public static void main(String[] args) {
       // 这个时间是什么时间?
       // 1970-01-01 00:00:00 001
       Date time = new Date(1);  // 注意:参数是一个毫秒

       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
       String strTime = sdf.format(time);
       // 北京是东8区,差8个小时
       System.out.println(strTime);  // 1970-01-01 08:00:00 001

       // 获取昨天的此时的时间
       Date time2 = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24);
       String strTime2 = sdf.format(time2);
       System.out.println(strTime2);


  }
}

 

 

5 数字相关类

5.1 数字格式化

package com.bjpowernode.javase.number;

/*
关于数字的格式化
*/

import java.text.DecimalFormat;

public class DecimalFormatTest01 {
   public static void main(String[] args) {
       // java.text.DecimalFormat专门负责数字格式化的
       // DecimalFormat df = new DecimalFormat("数字格式");

       /*
       数字格式有哪些?
           # 代表任意数字
           , 代表千分位
           . 代表小数点

           ###,###.##
               表示:加入千分位,保留2位小数
        */
       DecimalFormat df = new DecimalFormat("###,###.##");
       String s = df.format(1234.56);
       System.out.println(s);  // 1,234.56

       DecimalFormat df2 = new DecimalFormat("###,###.0000");  // 保留4位小数,不够补0
       String s2 = df2.format(1234.56);
       System.out.println(s2);  // 1,234.5600

  }
}

 

5.2 高精度的BigDecimal

package com.bjpowernode.javase.number;

/*
1、BigDecimal属于大数据,精度极高,不属于基本数据类型,属于java对象(引用数据类型)。这是SUN提供的一个类。专门用在账务软件当中。

2、注意:账务软件中double是不够用的,之前有一个学生去用友面试,经理就问了这样一个问题:
   你处理过账务数据吗?用的哪一种类型?
       千万别说double,说java.math.BigDecimal
*/

import java.math.BigDecimal;

public class BigDecimalTest01 {
   public static void main(String[] args) {
       // 这个100不是普通的100,是精度极高的100
       BigDecimal v1 = new BigDecimal(100);
       // 这个200不是普通的200,是精度极高的200
       BigDecimal v2 = new BigDecimal(200);

       // 求和
       // v1 + v2; // 这样不行,v1和v2都是引用,不能直接使用+求和
       BigDecimal v3 = v1.add(v2);  // 调用方法求和。
       System.out.println(v3);  // 300

       BigDecimal v4 = v2.divide(v1);
       System.out.println(v4);  // 2
  }
}

 

 

6 Random(随机数)

6.1 产生随机数

package com.bjpowernode.javase.random;

/*
随机数
*/

import java.util.Random;

public class RandomTest01 {
   public static void main(String[] args) {
       // 创建随机数对象
       Random random = new Random();

       // 随机产生一个int类型取值范围内的数字
       int num1 = random.nextInt();
       System.out.println(num1);

       // 产生[0~100]之间的随机数,不能产生101
       int num2 = random.nextInt(101);
       System.out.println(num2);
  }
}

 

6.2 生成5个不重复的随机数

package com.bjpowernode.javase.random;

/*
编写程序,生成5个不重复的随机数[0 ~ 100],重复的话重新生成。
最终生成的5个随机数放到数组中,要求数组中这5个随机数不重复。
*/

import java.util.Arrays;
import java.util.Random;

public class RandomTest02 {
   public static void main(String[] args) {
       // 创建Random对象
       Random random = new Random();

       // 准备一个长度为5的一维数组
       int[] arr = new int[5];  // 默认值都是0
       for(int i = 0; i < arr.length; i++){
           arr[i] = -1;
      }

       // 循环,生成随机数
       int index = 0;
       int count = 0;
       while(index < arr.length){
           // 生成随机数
           int num = random.nextInt(6);
           // 判断arr数组中有没历这个num
           // 如果没有这个num,就放进去。
           count++;
           if(!contains(arr, num)){
               arr[index] = num;
               index++;
          }
      }

       // 遍历以上的数组
       for(int i = 0; i < arr.length; i++){
           System.out.println(arr[i]);
      }
       System.out.println(count);
  }

   /**
    * 单独编写一个方法,这个方法专门用来判断数组中是否包含某个元素
    * @param arr 数组
    * @param key 元素
    * @return true表示包含,false表示不包含
    */
   public static boolean contains(int[] arr, int key){
       // 这个方案有bug
       /*
       // 对数组进制升序
       Arrays.sort(arr);
       // 进制二分法查找
       return Arrays.binarySearch(arr, key) >= 0;
        */

       for(int i = 0; i < arr.length; i++){
           if(arr[i] == key){
               return true;
          }
      }
       return false;
  }

}

 

 

7 Enum(枚举)

7.1 枚举的引入

package com.bjpowernode.javase.enum2;  // 标识符,关键字不能做标识符,enum是关键字。

/*
分析以下程序,在设计方面有什么缺陷?
*/

public class EnumTest01 {
   public static void main(String[] args) {
       // System.out.println(10 / 0); // java.lang.ArithmeticException: / by zero
       /*
       int retValue1 = divide(10, 2);
       System.out.println(retValue1);

       int retValue2 = divide(10, 0);
       System.out.println(retValue2);
        */

       boolean success = divide(10, 2);
       System.out.println(success ? "计算成功" : "计算失败");
       boolean success2 = divide(10, 0);
       System.out.println(success2 ? "计算成功" : "计算失败");
  }

   /**
    * 以下程序计算两个int类型数据的商,计算成功返回1,计算失败返回0
    * @param a int类型的数据
    * @param b int类型的数据
    * @return 返回1表示成功,返回0表示失败
    */
   // 设计缺陷?在这个方法的返回值类型上,返回一个int不恰当。
   // 既然最后的结果只是成功和失败,最好使用布尔类型,因为布尔类型true和false正好可以表示两种不同的状态。
   /*
   public static int divide(int a, int b){
       try{
           int c = a / b;
           // 程序执行到此处表示以上代码没有发生异常。表示执行成功,
           // 返回10已经偏离需求,实际上已经出错了,但是编译器没有检查出来
           // 我们一直想追求的是:所有的错误越早发现越好。
           return 10;
       } catch(Exception e){
           // 程序执行到此处表示以上程序出现了异常
           // 表示执行失败
           return 0;
       }
   }
    */

   // 这种设计不错
   public static boolean divide(int a, int b){
       try{
           int c = a / b;
           return true;
      } catch (Exception e){
           return false;
      }
  }

   /*
   思考:以上的这个方法设计没毛病,挺好,返回true和false表示两种情况
   但是在以后的开发中,有可能遇到一个方法的执行结果包括三种情况。
   四种情况,五种情况不等,但是每一个都是可以数清楚的,一枚一枚都是可以
   列举出来的,这个布尔类型就无法满足需求了。此时需要使用java语言中的枚举类型。
    */
}

 

7.2 枚举类型的使用

package com.bjpowernode.javase.enum2;

// 采用枚举的方式改造程序
/*
总结:
   1、枚举是一种引用数据类型
   2、枚举类型怎么定义,语法是?
       enum 枚举类型名{
           枚举值1, 枚举值2
       }
   3、结果只有两种情况的,建议使用布尔类型。结果超过两种并且还是可以一枚一枚列举出来的,建议使用枚举类型
       例如:颜色、季节等
*/

public class EnumTest02 {
   public static void main(String[] args) {
       Result r = divide(10, 0);
       System.out.println(r == Result.SUCCESS ? "计算成功" : "计算失败");
  }

   /**
    * 计算两个int类型数据的商
    * @param a int数据
    * @param b int数据
    * @return Result.SUCCESS表示成功,Result.FAIL表示失败
    */
   public static Result divide(int a, int b){
       try{
           int c = a / b;
           return Result.SUCCESS;
      } catch (Exception e) {
           return Result.FAIL;

      }
  }
}

// 枚举:一枚一枚可以列举出来的,才建议使用枚举类型。
// 枚举编译之后也是生成class文件。
// 枚举也是一种引用数据类型
// 枚举中的每一个值可以看做是常量
enum Result{
   // SUCCESS 是枚举Result类型中的一个值
   // FAIL 是枚举Result类型中的一个值
   // 枚举中的每一个值,可以看做是“常量”
   SUCCESS, FAIL
}

Season.java

package com.bjpowernode.javase.enum2;

/*
四季枚举类型
*/

public enum Season {
   SPRING, SUMMER, AUTUMN, WINTER
}

Color.java

package com.bjpowernode.javase.enum2;

/*
颜色枚举类型
*/

public enum Color {
   RED, BLUE, YELLOW, BLACK
}
 
posted @   路走  阅读(21)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 我与微信审核的“相爱相杀”看个人小程序副业
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示