第二章

  • 数组
  • String字符串
  • 包装类
数组

数组有哪些特性?

  1. Java语言中的数组是一种引用数据类型。不属于基本数据类型。数组的父类是Object。
  2. 数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的集合)。
  3. 数组当中可以存储 ”基本数据类型“ 的数据,也可以存储 ”引用数据类型“ 的数据
  4. 数组因为是引用数据类型,所以数组对象存储在堆内存当中
  5. 数组当中如果存储的是 “Java对象”的话,实际上存储的是对象的引用(内存地址)。
  6. 数组一旦创建,在Java中规定,数组长度不可变
  7. 数组分类:一维数组、二维数组、三维数组…
  8. 所有的数组对象都有length属性(Java自带的),用来获取数组中元素的个数。
  9. Java中的数组的类型要统一
  10. 数组中的元素内存地址连续的。
  11. 数组下标0~length-1。
  12. 数组将首元素的地址作为数组的地址。
  13. 数组这种数据结构的优缺点?

优点:查询/修改方便。

缺点:插入/删除 随机位置的元素 效率低。

数组无法存储大数据量,因为不能开辟较大的连续的内存空间。

  1. 怎样声明/定义一个一维的数组?

语法格式:

int[] array1;
double[] array2;
boolean[] array3;
String[] array4;
Object[] array5;
  1. 怎么初始化一维数组?
    包括两种方式:
//静态初始化一位数组
int[] array = {100,150.200,300};

//动态初始化一位数组
int[] array = new int[5];//默认5个元素且初始值都为0
public class ArrayTest01 {
    public static void main(String[] args) {
        int[] a1 = {10,200,300};//数组静态初始化方式

        int[] a2 = new int[5];//数组动态初始化方式

        System.out.println(a1[2]);
        System.out.println(a1.length);//length属性!!不是方法
        System.out.println(a1[a1.length-1]);//访问最后一个元素

        a1[0]=0;
        System.out.println(a1[0]);//第一个元素

        for (int i=0;i<a1.length;i++){
            System.out.println(a1[i]);
        }

        //System.out.println(a1[3]);//数组越界 异常java.lang.ArrayIndexOutOfBoundsException

        Object[] objects = new Object[5];//引用类型数组
        for(int i=0;i<objects.length;i++){
            System.out.println(objects[i]);
        }
    }
/*运行结果:
300
3
300
0
0
200
300
null
null
null
null
*/
public class ArrayTest02 {
    public static void main(String[] args) {
        String[] a = {"as","wd","wl","qe","rrr"};
        printArray(a);

        //printArray({"wl","ly","lhl"});//静态数组错误写法
        printArray(new String[]{"wl","ly","lhl"});//传静态数组的写法
    }
    public static void printArray(String[] s){
        for (int i=0;i<s.length;i++){
            System.out.println(s[i]);
        }
    }
}
public class ArrayTest07 {
    public static void main(String[] args) {
        Animal a1 = new Animal();
        Animal a2 = new Animal();
        Animal a3 = new Animal();
        Animal[] animals = {a1,a2,a3};

        for (int i=0;i<animals.length;i++){
            animals[i].move();
        }
    }
}
class Animal{
    public void move(){
        System.out.println("Animal move...");
    }
}

Java中的数组扩容:创建一个大数组,将原来的数组一个一个拷贝到大数组中。(数组扩容效率低)

System.arraycopy(src,secPos,dest,destPos, length);

/*
数组扩容System.arraycopy(src,secPos,dest,destPos, length);
src:原数组,secPos:原数组拷贝起点
dest:大数组,destPos:大数组起点
length:拷贝长度
 */
public class ArrayTest08 {
    public static void main(String[] args) {
        int[] src = {1,2,3};
        int[] dest = new int[5];
        System.arraycopy(src,0,dest,1, 2);
        for(int i=0;i<dest.length;i++){
            System.out.println(dest[i]);
        }

        Object[] objects = {new Object(),new Object(),new Object()};
        Object[] newObjects = new Object[10];
        System.arraycopy(objects, 0, newObjects, 0, objects.length);
        for(int i=0;i<newObjects.length;i++){
            System.out.println(newObjects[i]);//存放对象地址
        }
    }
}

数组内存图:

java 对象数组的存储 数组对象在java中存储在()中_数据结构

遍历二维数组:

/*
二维数组遍历
 */
public class ArrayTest09 {
    public static void main(String[] args) {
        String[][] array = {{"java","oracle","c++","python","c#"},
                            {"张三","李四","王五"},
                            {"lucy","jack","rose"}
        };
        for(int i=0;i<array.length;i++){
            for (int j=0;j<array[i].length;j++){
                System.out.println(array[i][j]);
            }
        }
    }
}
public class ArrayTest10 {
    public static void main(String[] args) {
        int[][] array = new int[3][4];
        int[][] array2 = {{1,2,3},{4,5,6},{7,8,9}};
        printArray(array2);
        printArray(new int[][]{{1,2,3},{4,5,6},{7,8,9}});//写法二
    }
    public static void printArray(int[][] array){
        for (int i=0;i<array.length;i++){
            for (int j=0;j<array[i].length;j++){
                System.out.print(array[i][j]+" ");
            }
            System.out.println();
        }
    }
}
练习1:使用一维数组模拟栈数据结构

以下代码可改进:将array用Object类型,这样可以装所有的引用类型。

弹栈pop时要返回该元素。

//一维数组模拟栈
import java.util.Arrays;
public class Stack {
    private int[] array = new int[5];
    private int length;

    public Stack() {
    }

    public Stack(int[] array, int length) {
        this.array = array;
        this.length = length;
    }

    public void push(int x){//入栈
        if (length==5){
            System.out.println("栈满!!!");
            return;
        }
        array[length++]=x;
    }


    public int pop(){//出栈
        if(length==0){
            System.out.println("栈空!!!");
            return -1;
        }
        return array[--length];//出栈
    }
    public void printArray(){//打印
        for (int i=0;i<length;i++){
            System.out.println(array[i]);
        }
    }

    public int[] getArray() {
        return array;
    }

    public void setArray(int[] array) {
        this.array = array;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    @Override
    public String toString() {
        return "Stack{" +
                "array=" + Arrays.toString(array) +
                ", length=" + length +
                '}';
    }
}
//测试类
public class ArrayTest11 {
    public static void main(String[] args) {
        Stack stack = new Stack();
        stack.push(1);
        stack.push(2);
        stack.push(8);
        stack.push(10);
        stack.printArray();
        System.out.println("===============================================");
        stack.pop();
        stack.pop();
        stack.pop();
        stack.printArray();
        System.out.println("===============================================");
        stack.push(2);
        stack.push(3);
        stack.push(4);
        stack.push(5);
        stack.push(6);//栈满
        System.out.println("===============================================");
        stack.pop();
        stack.pop();
        stack.pop();
        stack.pop();
        stack.pop();
        stack.pop();//栈空
    }
}

/*测试结果:
1
2
8
10
===============================================
1
===============================================
栈满!!!
===============================================
栈空!!!

*/
练习2:酒店系统

详细代码见p572

//房间类
public class Room {
    private int roomId;//房间编号
    private String kind;//房间类型
    private int state;//0表示空闲,

    public Room() {
    }

    public Room(int roomId, String kind, int state) {
        this.roomId = roomId;
        this.kind = kind;
        this.state = state;
    }

    public int getRoomId() {
        return roomId;
    }

    public void setRoomId(int roomId) {
        this.roomId = roomId;
    }

    public String getKind() {
        return kind;
    }

    public void setKind(String kind) {
        this.kind = kind;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    @Override
    public String toString() {
        return "Room{" +
                "roomId=" + roomId +
                ", kind='" + kind + '\'' +
                ", state=" + state +
                '}';
    }
}
//酒店类
public class Hotel {
    private Room[][] rooms;

    public Hotel() {
    }

    public Hotel(Room[][] rooms) {
        this.rooms = rooms;
    }

    public void book(int x,int y){//订房
        if(rooms[x][y].getState()==1){
            System.out.println("该房间已被占用!!!");
            return;
        }
        rooms[x][y].setState(1);//订房
        System.out.println("订房成功!!!");
    }

    public void cancel(int x,int y){//退房
        if (rooms[x][y].getState()==0){
            System.out.println("已退房!!!");
        }
        rooms[x][y].setState(0);//退房
        System.out.println("退房成功!!!");
    }

    public void printRooms(){//打印
        for(int i=1;i<rooms.length;i++){
            for (int j=1;j<rooms[i].length;j++){
                System.out.println(i+"层"+j+"号房间状态:"+rooms[i][j].getState());
            }
        }
    }
    
    public Room[][] getRooms() {
        return rooms;
    }
    
    public void setRooms(Room[][] rooms) {
        this.rooms = rooms;
    }

    @Override
    public String toString() {
        return "Hotel{" +
                "rooms=" + Arrays.toString(rooms) +
                '}';
    }
}
//测试类
/*
编写一个酒店管理系统:模拟订房、退房、打印所有房间的状态等功能
1、该系统的用户是:酒店前台。
2、酒店的所有房间使用二维数组来模拟。Room[][] rooms;
3、酒店的每一个房间应该是一个java对象:Room
4、每个房间有:房间编号、房间类型属性、房间是否空闲。
5、系统对外提供的功能:
    可以预定房间:用户输入房间编号,订房。
    可以退房: 用户输入房间编号,退房。
    可以查看所有房间的状态:用户输入某个指令应该可以查看所有房间的状态。
 */
public class Test {
    public static void main(String[] args) {
        java.util.Scanner sr = new java.util.Scanner(System.in);
        Room[][] rooms = new Room[11][11];
        for (int i=1;i<rooms.length;i++){//初始化酒店
            for (int j=1;j<rooms[i].length;j++){
                rooms[i][j]=new Room();
            }
        }

        Hotel hotel = new Hotel(rooms);
        int x = sr.nextInt();
        int y = sr.nextInt();
        hotel.book(x, y);//预订
        hotel.printRooms();
        hotel.book(x, y);//重复预订
        System.out.println("====================================");
        hotel.cancel(x, y);//退房
        hotel.printRooms();
        hotel.cancel(x, y);//重复退房

    }
}

Arrays工具类:IDEA tips:双击shift查关键字 Arraysctrl+F12查看类的所有方法列表!!

java.util.Arrays工具类的方法都是静态,直接用类名调用

主要使用的是两个方法:二分查找、排序。

import java.util.Arrays;

public class ArrayTest15 {
    public static void main(String[] args) {
        int[] arrays={9,8,7,6,5,4,3,2,1};
        Arrays.sort(arrays);//排序
        for (int i=0;i<arrays.length;i++){
            System.out.println(arrays[i]);
        }
        System.out.println("=======================");
        int index=Arrays.binarySearch(arrays, 6);//二分查找
        System.out.println("查找元素下标:"+index);

    }
}

数组常见的算法:

冒泡排序

选择排序

二分查找

//冒泡
import java.util.Arrays;

public class ArrayTest12 {
    public static void main(String[] args) {
        //工具类中的方法大部分都是静态方法
        int[] array = {5,6,3,8,7,9,2,1};
        //Arrays.sort(array);//直接调Arrays类库的排序方法
        bubbleSort(array);
        for (int i=0;i<array.length;i++){
            System.out.println(array[i]);
        }
    }

    public static void bubbleSort(int[] arrays){//冒泡
        int n = arrays.length;
        //写法一
        /*for (int i=1;i<n;i++){
            for (int j=0;j<n-i;j++){
                if (arrays[j]>arrays[j+1]){
                    int t=arrays[j];
                    arrays[j]=arrays[j+1];
                    arrays[j+1]=t;
                }
            }
        }*/
        //写法二
        for (int i=n-1;i>0;i--){
            for (int j=0;j<i;j++){
                if (arrays[j]>arrays[j+1]){
                    int t=arrays[j];
                    arrays[j]=arrays[j+1];
                    arrays[j+1]=t;
                }
            }
        }
    }
}
//选择排序
public class ArrayTest13 {
    public static void main(String[] args) {
        int[] array = {5,6,3,8,7,9,2,1};
        selectSort(array);
        for (int i=0;i<array.length;i++){
            System.out.println(array[i]);
        }
    }
    public static void selectSort(int[] arrays){//每一趟确定一个最小值
        int n=arrays.length;
        //写法一
        /*for (int i=0;i<n;i++){
            int minIndex=i;
            for(int j=i;j<n;j++){
                if (arrays[minIndex]>arrays[j]){
                    minIndex=j;
                }
            }
            int t=arrays[i];//交换,确定一个位置
            arrays[i]=arrays[minIndex];
            arrays[minIndex]=t;
        }*/
        //写法二
        for (int i=n-1;i>0;i--){//每一趟确定一个最大值
            int maxIndex=i;
            for (int j=0;j<i;j++){
                if (arrays[maxIndex]<arrays[j]){
                    maxIndex=j;
                }
            }
            int t=arrays[i];//交换,确定一个位置
            arrays[i]=arrays[maxIndex];
            arrays[maxIndex]=t;
        }
    }
}
//二分查找
public class ArrayTest14 {
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5,6,7,8,9,10};
        int index=binarySearch(array, 6);
        System.out.println(index);
    }
    public static int binarySearch(int[] arrays,int x){
        int l=0,r=arrays.length-1;
        while (l<=r){
            int mid=(r+l)/2;
            if (x<arrays[mid]){
                r=mid-1;
            }
            else if (x==arrays[mid]){
                return mid;
            }
            else {
                l=mid+1;
            }
        }
        return -1;
    }
}
String字符串
  1. String
  2. StringBuffer
  3. 继承类型对应的8个包装类
  4. 面试题
  5. 日期相关类
  6. Random
  7. Enum
public class StringTest {
    public static void main(String[] args) {
        String s1 = "abcdef";
        String s2  = "abcdef"+"xy";//一个一共创建了3个对象

        String s3 = new String("xy");//内存图  new的时候一定在堆中开辟空间
    }
}

注:s1保存的是方法区常量池"abcdef"的内存地址,而不是字符串

以上代码内存图如下:

java 对象数组的存储 数组对象在java中存储在()中_数据结构_02

String s1="abc";
String s2="abc";
System.out.println(s1==s2);//true or false ?
//true 因为"abc"存放在方法区的字符串常量池中,可以重复使用,指向同一个"abc",所以为true

String x=new String("xyz");
String y=new String("xyz");
System.out.println(x==y);//true or false ?
//false 因为堆创建的两个对象是不一样的
System.out.println(x.equals(y));//true or false ?
//true 因为String重写了equals方法

//结论:字符串比较不能用==号,应该重写equals方法,用equals方法比较即可

以上代码内存图如下:

java 对象数组的存储 数组对象在java中存储在()中_java_03

tips:垃圾回收器不会回收常量池的对象,回收的是堆区的。

String字符串常用的构造方法:
/**
 *关于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 StringTest02 {
    public static void main(String[] args) {
        String s1 = "hello world";

        //常用构造方法

        //1、将bytes数组转换为对应的ascii字符,并拼接为字符串。
        byte[] bytes = {97,98,99};//97是a,98是b,99是c
        String s2 = new String(bytes);
        System.out.println(s2);//abc

        String s3 = new String(bytes, 1, 2);//截取部分元素转化为字符串
        System.out.println(s3);//bc

        //2、将char数组转化为字符串。
        char[] chars = {'x','y','z'};
        String s4 = new String(chars);
        System.out.println(s4);//xyz

        String s5 = new String(chars,1,2);//截取部分元素转化为字符串
        System.out.println(s5);//yz

    }
}
String类常用方法:
/**
 * 常见字符串方法
 *1、char c=s.charAt(1);
 *2、int ret = s.compareTo(s2);
 *3、String ss = s.concat(s2);
 *4、boolean flat = s2.contains(s3);
 *5、boolean flat2 = s2.endsWith(s3);
 *   boolean flat6 = "http://baidu.com".startsWith("http");
 *6、boolean flat3 = s.equals(s2);
 *7、boolean flat4 = "abC".equalsIgnoreCase("ABc");
 *8、byte[] bytes = "abcdefg".getBytes();
 *9、int index = "oraclec++.netc#phppythonc++java".indexOf("java");
 *   int index = "oraclec++.netc#phppythonc++java".lastIndexOf("java");
 *10、boolean flat5 = str.isEmpty();
 *11、int length = "sdskds".length();
 *12、String newStr="http://www.baidu.com".replace("http://","https://");
 *13、String[] strs = "1999-11-29".split("-");
 *14、String str3 = "http://www.baidu.com".substring(7);//www.baidu.com
 *15、String str4 = "http://www.baidu.com".substring(7, 10);//www 左闭右开区间
 *16、char[] chars = "abcdefg".toCharArray();
 *17、String str5 = "ABCDEf".toLowerCase();
 *    String str6 = "abcdEf".toUpperCase();
 *18、String str7 = "    zhangsan   ".trim();
 *19、String ss1 =String.valueOf(true);
 *    String ss2 = String.valueOf(123);
 *    //这个静态的valueOf()方法,参数是一个对象的时候,会自动调用对象的toString方法吗?  会!!!
 *    //println(对象),当直接打印对象的时候会自动调用String.valueOf(对象)方法 然后调toString方法
 *    String ss3 = String.valueOf(new Customer());
 *
 */
public class StringTest03 {
    public static void main(String[] args) {
        String s = "abcdefgh";
        String s2 = "abcdf";
        String s3 = "abc";

        //1、根据下标取字符
        char c=s.charAt(1);
        System.out.println(c);

        //2、比较两个字符串大小
        int ret = s.compareTo(s2);
        System.out.println(ret);//s小于s2所以返回-1

        //3、拼接字符串
        String ss = s.concat(s2);
        System.out.println(ss);

        //4、判断字符串是否包含
        boolean flat = s2.contains(s3);
        System.out.println(flat);//s2包含s3

        //5、判断字符串s2是否以字符串s3结尾
        boolean flat2 = s2.endsWith(s3);
        System.out.println(flat2);//false
        boolean flat6 = "http://baidu.com".startsWith("http");//判断字符串是否以某个子串开头
        System.out.println(flat6);


        //6、比较两个字符串必须使用equals方法,不能使用"=="
        //老版本的equals调的的compareTo方法,新版本是将两字符串转为byte数组进行比较!!!
        boolean flat3 = s.equals(s2);
        System.out.println(flat3);//false

        //7、判断两个字符串是否相等,并同时忽略大小写
        boolean flat4 = "abC".equalsIgnoreCase("ABc");
        System.out.println(flat4);//true

        //8、将字符串转化为字节数组
        byte[] bytes = "abcdefg".getBytes();
        for(int i=0;i<bytes.length;i++){
            System.out.println(bytes[i]);
        }

        //9、判断某个子串在当前字符串中第一次出现处的索引。
        int index = "oraclec++.netc#phppythonc++java".indexOf("java");
        System.out.println(index);//27

        //判断某个子串在当前字符串中最后一次出现处的索引。
        int index2 = "oraclec++.netc#phppythonc++java".lastIndexOf("c++");
        System.out.println(index2);//24

        //10、判断某个字符串是否为空
        String str="";
        boolean flat5 = str.isEmpty();
        System.out.println(flat5);//true

        //11、字符串长度
        int length = "sdskds".length();
        System.out.println(length);

        //12、替换方法
        String newStr="http://www.baidu.com".replace("http://","https://");
        System.out.println(newStr);
        String newStr2 = "name=zhangsan&password=123&age=20".replace("=", ":");
        System.out.println(newStr2);

        //13、拆分字符串(拆分后存到字符数组当中)
        String[] strs = "1999-11-29".split("-");
        for (int i=0;i<strs.length;i++){
            System.out.println(strs[i]);
        }
        String[] strs2 = "name=zhangsan&password=123&age=20".split("&");
        for (int i=0;i< strs2.length;i++){
            System.out.println(strs2[i]);
        }

        //14、截取字符串
        String str3 = "http://www.baidu.com".substring(7);//www.baidu.com
        System.out.println(str3);
        String str4 = "http://www.baidu.com".substring(7, 10);//www 左闭右开区间
        System.out.println(str4);

        //15、将字符串转换为字符串数组
        char[] chars = "abcdefg".toCharArray();
        for (int i=0;i<chars.length;i++){
            System.out.println(chars[i]);
        }

        //16、将字符串转换为全大写/小写
        String str5 = "ABCDEf".toLowerCase();
        String str6 = "abcdEf".toUpperCase();
        System.out.println(str5);
        System.out.println(str6);

        //17、去除字符串前后空白(中间空白不去除!!!)
        String str7 = "    zhang  san   ".trim();
        System.out.println(str7);

        //18、将非字符串转换为字符串
        String ss1 =String.valueOf(true);
        System.out.println(ss1);
        String ss2 = String.valueOf(123);
        System.out.println(ss2);

        //这个静态的valueOf()方法,参数是一个对象的时候,会自动调用对象的toString方法吗?  会!!!
        //println(对象)当直接打印对象的时候会自动调用String.valueOf(对象)方法 然后调toString方法
        String ss3 = String.valueOf(new Customer());
        System.out.println(ss3);

    }
}
class Customer{
    //没有重写toString方法前打印的是是对象地址

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

思考:为什么引入StringBuffer字符串?

因为字符串的+拼接符会导致创建很多对象在方法区常量池

例如:String s=“abc”;

String s2=“xyz”;

String s+=s2;

这个过程中会在方法区常量池创建3个对象

StringBuffer的初始化容量为16的byte[]数组

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

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

        //拼接字符串,以后拼接字符串统一调用append()方法。不要使用+来拼接了!!!
        sbf.append("ab");
        sbf.append("cd");
        sbf.append("e");
        sbf.append(3.14);
        sbf.append(true);
        sbf.append(100L);
        //append方法底层在追加的时候,如果byte[]数组满了会自动扩容。
        System.out.println(sbf);
    }
}
String和StringBuffer的区别:

java 对象数组的存储 数组对象在java中存储在()中_数组_04

String底层的byte数组被final修饰了,需要创建新的对象:private final char value[];

而StringBuffer底层的byte数组 没有被final修饰:,可以被修改,修改后原来的数组空间就会被回收,节省空间:private transient char[] toStringCache;

java 对象数组的存储 数组对象在java中存储在()中_jvm_05

如何优化StringBuffer的性能?

在创建StringBuffer的时候尽量给定一个初始化容量。

最好减少底层数组的扩容的次数。预估以下,给一个大一些的初始容量。

关键点:给一个合适的初始化容量。可以提高程序的执行效率。(即减少扩容的次数)

StringBuilder

StringBuffer是线程安全的。(安全所以效率低)

StringBuilder是非线程安全的。(效率高)

多线程建议使用StringBuffer。

单线程建议使用StringBuilder。

/**
 * java.lang.StringBuilder
 * StringBuffer和StringBuilder的区别?
 * StringBuffer中的方法都有synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的。
 * StringBuilder中的方法没都有synchronized关键字修饰。表示StringBuilder在多线程环境下运行是不安全的。
 */
public class StringBuildTest01 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append(100);
        sb.append(true);
        sb.append("hello");

        System.out.println(sb);
    }
}
包装类
/**
 * 1、java中为8种基本数据类型又对应准备了8种包装类型。8种包装类型属于引用数据类型,父类是Object。
 * 2、为什么要提供8中包装类?因为当参数列表是Object类型的时候,基本数据类型传不了。
 *
 * 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.lang.Boolean(父类Object)
 * char                    java.lang.Character(父类Object)
 *
 * 以java.lang.Integer为例,其他类似。
 * 实现了 基本数据类型(拆箱)<==>引用数据类型(装箱) 的相互转化。
 *
 * Number是一个抽象类,无法实例化对象。
 * Number类中有这样的方法:
 * byte byteValue() 以byte形式返回指定数值。
 * abstract double doubleValue() 以double形式返回指定的数据。
 * abstract float floatValue() 以float形式返回指定的数据。
 * abstract int intValue() 以int形式返回指定的数据。
 * abstract long longValue() 以long形式返回指定的数据。
 * abstract short shortValue() 以short形式返回指定的数据。
 * 这些方法其实子类所有数字的包装类的子类都有,这些方法是负责拆箱的。
 */
public class IntegerTest01 {
    public static void main(String[] args) {

        //装箱
        Integer i = new Integer(123);//java9之后该方法已过时。

        //拆箱
        float f = i.floatValue();
        System.out.println(f);


    }
}
/*
  关于Integer类型的构造方法有两个:
  		Integer(int)
  		Integer(String)
  其他包装类类似。
 
*/
public class IntegerTest02 {
    public static void main(String[] args) {

        Integer x = new Integer("123");//String 转 Integer
        System.out.println(x);

        Double d = new Double("3.14");//String 转 Double
        System.out.println(d);

        Double e = new Double(1.23);
        System.out.println(e);
    }
}
/**
 * 好消息:在JDK1.5之后,支持自动拆箱和自动装箱了。
 */
public class IntegerTest04 {
    public static void main(String[] args) {
        //自动装箱 int => Integer
        Integer i = 100;

        //自动拆箱 Integer => int
        int x = i;

    }
}
面试题

面试题1

java 对象数组的存储 数组对象在java中存储在()中_数据结构_06

==注意:==字符串不可变是什么意思?

是说双引号里面的字符串对象一旦创建不可变。(即底层源码中的byte数组的引用value) ,但是s没有被final修饰,s是可以改变的!!!

String s = "abc";

//s变量是可以执行其他对象的
//字符串不可变不是说变量s不可变,说的是"abc"这个对象不可变!
s = "xyz";
public class IntegerTest05 {
    public static void main(String[] args) {

        //自动装箱
        Integer z = 1000;
        //自动拆箱并参与运算 加减乘除会自动拆箱
        System.out.println(z+1);

        Integer a = 1000;
        Integer b = 1000;
        //因为自动装箱是等同于Integer a = new Integer(1000);堆中的对象,地址a、b显然不一样!!!
        //双等号是不会自动拆箱的
        System.out.println(a==b);//false

    }
}

面试题2(重要!!!

/**
 * java中为了提高程序的效率,在类加载的时候 将[-128,127]之间所有的包装对象提前创建好,
 * 放到了一个方法区的“整数型常量池”当中了,目的是只要用这个区间的数据不需要
 * 再new了,直接从整数型常量池取出来。
 *
 * 原理:x变量中保存的对象的内存地址和y变量中保存的内存地址是一样的。
 *
 */
public class IntegerTest06 {
    public static void main(String[] args) {
        Integer a = 128;
        Integer b = 128;
        System.out.println(a==b);//false

        Integer x = 127;
        Integer y = 127;
        System.out.println(x==y);//true
    }
}

java 对象数组的存储 数组对象在java中存储在()中_java 对象数组的存储_07

Integer 常用方法:

重点方法:static int parseInt(String s)

/**
 * 总结一下之前学的经典的异常:
 * 空指针异常:NullPointerException
 * 类型转换异常:ClassCastException
 * 数组下标越界异常:IndexOutOfBoundsException
 * 数字格式化异常:NumberFormatException
 */
public class IntegerTest07 {
    public static void main(String[] args) {

        //1
        //手动装箱
        Integer x = new Integer(1000);

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

        //2
        Integer a = new Integer("123");

        //编译器运行时会报java.lang.NumberFormatException异常。
        //Integer b = new Integer("中文");

        //3、重点方法 将字符串String直接转化为int类型!!!
        //static int parseInt(String s)
        //静态方法,传参String,返回int
        //网页中的文本框存储的实际上是"123"字符串。后台数据库要求存储123数字,此时java查询要将"123"转化为123
        int ret = Integer.parseInt("123");
        System.out.println(ret);

        //照葫芦画瓢 其他包装类型一样
        double d = Double.parseDouble("3.14");
        System.out.println(d+1);//4.140000000000001(精度问题)

        float f = Float.parseFloat("5.25");
        System.out.println(f+1);//6.25

        //toString方法中,java.lang.Object@1b6d3586  1b6d3586是将hashcode()的10进制转化为了16进制
        //调用了Integer.toHexString(hashCode());方法
        System.out.println(new Object());

        //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("100");
        System.out.println(i2);
    }
}
}
String int Integer转化!!

java 对象数组的存储 数组对象在java中存储在()中_jvm_08

/**
 * String int Integer之间互相转换
 */
public class IntegerTest08 {
    public static void main(String[] args) {
        //String -->int
        String s = "123";
        int x = Integer.parseInt(s);

        //int-->String
        int x2 = 100;
        String s2 = 100+"";
        //String s2 = String.valueOf(x2);

        //int-->Integer
        Integer i =24;//自动装箱
        //int x3 = 24;
        //Integer i = Integer.valueOf(x3);

        //Integer-->int
        Integer i2 = new Integer(100);
        int x4 =i2;//自动拆箱
        //int x4 = i2.intValue();

        //String-->Integer
        String s3 = "256";
        Integer i3 = Integer.valueOf(s3);

        //Integer-->String
        Integer i4 = 100;
        String s4 = String.valueOf(i4);
    }
}
日期相关类

String —> Date

Date —> String

/**
 * java中对日期的处理
 * 这个例子主要掌握
 *          String ---> Date
 *          Date ---> String
 * 用到了SimpleDateFormat类
 */
public class DateTest01 {
    public static void main(String[] args) throws ParseException {

        //获取系统当前时间,直接调用无参构造方法。显然Date类的toString()方法被重写了。
        Date date =new Date();
        System.out.println(date);//Sun Oct 02 15:30:09 CST 2022

        //日期格式化
        //将日期类型Date,按照指定的格式进行转换:Date --转换成具有一定格式的日期字符串-->String
        //SimpleDateFormat是java.text包下的。专门负责日期格式化的。
        /*
        yyyy 年(年是四位)
        MM 月(月是两位)
        dd 日
        HH 时
        mm 分
        ss 秒
        SSS 毫秒(毫秒三位,最高999。1000毫秒代表1秒)
         */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String newdate = sdf.format(date);
        System.out.println(newdate);

        //假设现在有一个日期字符串String,怎么转换成Date类型?格式必须一致才可以,否则报java.text.ParseException异常
        String time ="2008-08-08 08:08:08 888";
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        Date date1 = sdf2.parse(time);
        System.out.println(date1);
    }
}

计算耗时:

/**
 * 获取自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日 00:00:00 000到当前系统时间的总毫秒数。
 * System.arraycopy(src,srcPos , dest,destPos ,length ); 数组扩容方法
 * System.exit(0) 退出JVM。
 *
 */
public class DateTest02 {
    public static void main(String[] args) {

        //获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数。
        long nowTimeMillis = System.currentTimeMillis();
        System.out.println(nowTimeMillis);//1664698766609

        long startTime = System.currentTimeMillis();
        print();
        long endTime = System.currentTimeMillis();
        System.out.println("一共耗费"+(endTime-startTime)+"毫秒");//一共耗费17毫秒(不打印0毫秒)
    }
    //需求:统计一个方法执行所耗费的时长
    public static void print(){
        for (int i=0;i<1000;i++){
            System.out.println("i="+i);
        }
    }

}

Date类的有参构造方法:

/**
 * Date的有参构造方法:
 * Date time = new Date(1);//1970年1月1日 00:00:00 001 毫秒
 * System.currentTimeMillis()是指1970年1月1日 00:00:00 000毫秒 到 当前时间的总毫秒数
 */
public class DateTest03 {
    public static void main(String[] args) {
        Date time = new Date(1);//1970年1月1日 00:00:00 001 毫秒
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String newTime = sdf.format(time);
        //北京是东8区。差8个小时。
        System.out.println(newTime);//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);//2022-10-01 17:00:26 039

        //获取去年此时的时间
        Date time3 = new Date(System.currentTimeMillis()-1000*60*60*24*365L);//超过int范围, 可以用L转long
        String strTime3 = sdf.format(time3);
        System.out.println(strTime3);//2021-10-02 17:08:04 086
    }
}
DecimalFormat数字格式化
/**
 * 关于数字的格式化(了解)
 *
 */
public class DecimalFormatTest01 {
    public static void main(String[] args) {
        //java.text.DecimalFormat专门负责数字格式化的。
        //DecimalFormat df = new DecimalFormat("数字格式");

        /*
        数字格式有哪些?
        # 代表任意数字
        , 代表千分位
        . 代表小数点
        0 代表不够时补0
         */
        DecimalFormat df = new DecimalFormat("###,###.##");
        String newNum = df.format(1234.56654);//1,234.57
        System.out.println(newNum);

        DecimalFormat df2 = new DecimalFormat("###,###.0000");
        String newNum2 = df2.format(12345.78);
        System.out.println(newNum2);//12,345.7800
    }
}
BigDecimal(高精度)
/**
 *1、 BigDecimal 属于大数据,精度极高,不属于基本数据类型,属于java对象(引用数据类型)、
 * 这是SUN提供的一个类。专门用在财务软件当中。
 *
 * 2、财务软件中double是不够的。
 * 你处理过财务数据吗?用的哪一种类型?
 *   千万别说double,说java.math.BigDecimal
 *
 *  3、BigDecimal之间的运算都是调用方法来计算结果的。
 *
 */
public class BigDecimalTest {
    public static void main(String[] args) {
        //这个100不是普通的100,是精度极高的100
        BigDecimal v1 = new BigDecimal(100);
        //精度极高的200
        BigDecimal v2 = new BigDecimal(200);
        //求和
        //v1+v2;  //这样不行,v1和v2都是引用,不能直接使用+求和。
        BigDecimal v = v1.add(v2);
        System.out.println(v);//300

        BigDecimal vv = v1.divide(v2);
        System.out.println(vv);//0.5
    }
}
Random随机数
/**
 * 随机数
 */
public class RandomTest01 {
    public static void main(String[] args) {
        //创建随机数对象
        Random random = new Random();

        //随机产生一个int范围内的一个随机数
        int num = random.nextInt();
        System.out.println(num);//-362127713

        //产生[0,100]之间的随机数。不能产生101
        //nextInt翻译为:下一个int类型的数据是101,表示只能取到100。
        int num2 = random.nextInt(101);//不包括101
        System.out.println(num2);

    }
}
练习(随机数)

编写程序:生成5个不重复的随机数。重复的话随机生成。

最终生成的5个随机数放到数组中,要求数组中这5个随机数不重复。

/**
 * 编写程序:生成5个不重复的随机数。重复的话随机生成。
 * 最终生成的5个随机数放到数组中,要求数组中这5个随机数不重复。
 */
public class RandomTest02 {
    public static void main(String[] args) {
        int[] nums = new int[5];
        Random random = new Random();
        int i=0;//代表有i个元素已存入数组

        while (true){
            if (i==5) break;
            int x = random.nextInt(5);
            System.out.println("x="+x);
            int j;
            for (j=0;j<i;j++){
                if (nums[j]==x){//重复
                    break;
                }
            }
            if (i==j){//没有重复
                nums[i++]=x;
            }
        }

        for (int k=0;k<5;k++){
            System.out.println(nums[k]);
        }
    }
}
/*
结果:
x=1
x=1
x=4
x=3
x=4
x=3
x=2
x=1
x=4
x=4
x=4
x=0
1
4
3
2
0
*/
枚举enum

为什么要用到枚举?

java 对象数组的存储 数组对象在java中存储在()中_数据结构_09

思考:以上的方法设计没毛病,挺好,返回true和false两种情况,

但是在以后的开发中,有可能遇到一个方法的执行结果可能包括三种情况,

四种情况,五种情况不等,但没说每一个都是可以数清楚的,一枚一枚

都可以列举出了。这个布尔类型就无法满足需求了。此时需要使用java语言中

的枚举类型。