第二章
- 数组
- String字符串
- 包装类
数组
数组有哪些特性?
-
Java语言中的数组是一种
引用数据类型
。不属于基本数据类型。数组的父类是Object。 - 数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的集合)。
-
数组当中可以
存储 ”基本数据类型“ 的数据
,也可以
存储 ”引用数据类型“ 的数据
。 -
数组因为是引用数据类型,所以
数组对象存储在堆内存当中
。 -
数组当中如果存储的是 “Java对象”的话,实际上存储的是对象的
引用
(
内存地址
)。 -
数组一旦创建,在Java中规定,
数组长度不可变
。 - 数组分类:一维数组、二维数组、三维数组…
-
所有的数组对象都有
length属性
(Java自带的),用来获取数组中元素的个数。 -
Java中的数组的
类型要统一
。 -
数组中的元素
内存地址连续
的。 - 数组下标0~length-1。
- 数组将首元素的地址作为数组的地址。
- 数组这种数据结构的优缺点?
优点:查询/修改方便。
缺点:插入/删除 随机位置的元素 效率低。
数组
无法存储大数据量
,因为不能开辟较大的连续的内存空间。
- 怎样声明/定义一个一维的数组?
语法格式:
int[] array1;
double[] array2;
boolean[] array3;
String[] array4;
Object[] array5;
-
怎么初始化一维数组?
包括两种方式:
//静态初始化一位数组 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]);//存放对象地址
}
}
}
数组内存图:
遍历二维数组:
/*
二维数组遍历
*/
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查关键字 Arrays
、
ctrl+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字符串
- String
- StringBuffer
- 继承类型对应的8个包装类
- 面试题
- 日期相关类
- Random
- 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”的内存地址,而不是字符串
以上代码内存图如下:
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方法比较即可
以上代码内存图如下:
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的区别:
==String、StringBuffer、StringBuilder的区别?==详细见:https://blog.csdn.net/weixin_45433031/article/details/110728559
String底层的byte数组被final修饰了,需要创建新的对象:private final char value[];
而StringBuffer底层的byte数组 没有被final修饰:,可以被修改,修改后原来的数组空间就会被回收,节省空间:private transient char[] toStringCache;
如何优化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
==注意:==字符串不可变是什么意思?
是说双引号里面的字符串对象一旦创建不可变。(即底层源码中的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
}
}
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转化!!
/**
* 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
为什么要用到枚举?
思考:以上的方法设计没毛病,挺好,返回true和false两种情况,
但是在以后的开发中,有可能遇到一个方法的执行结果可能包括三种情况,
四种情况,五种情况不等,但没说每一个都是可以数清楚的,一枚一枚
都可以列举出了。这个布尔类型就无法满足需求了。此时需要使用java语言中
的枚举类型。