包装类
包装类存在的意义
MyInt.class
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 "[value = " + value + "]";
return String.valueOf(value);
}
}
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);
//System.out.println(myInt);// 100
}
public static void doSome(Object obj) {
System.out.println(obj);
}
}
八种包装类都是什么 以及 装箱和拆箱的概念
package com.bjpowernode.javase.integer;
/**
1、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)
2、以上八种包装类中,重点以java.lang.Integer为代表进行学习,其他的类型都是照葫芦画瓢就行。
3、8种包装类中其中6个都是数字对应的包装类,他们的父类都是Number,可以先研究一下Number中公共的方法。
Number是一个抽象类,无法实例化对象。
Number类中有这样的方法:
byte byteValue()
abstract double doubleValue()
abstract float floatValue()
abstract int intValue()
abstract long longValue()
short shortValue()
其实这些方法所有的数字包装类,子类都有,这些方法是负责拆箱的。
*/
public class InterTest02 {
public static void main(String[] args) {
// 基本数据类型 --(转换成)--> 引用数据类型(装箱)
Integer i = new Integer(123);
// 引用数据类型 --(转换成)--> 基本数据类型(拆箱)
float f = i.floatValue();
System.out.println(f);// 123.0
int retValue = i.intValue();
System.out.println(retValue);// 123
}
}
Integer的构造方法
package com.bjpowernode.javase.integer;
/**
1、关于Integer类的构造方法有两个,如下:
Integer(int)
Integer(String)
*/
public class IntegerTest03 {
public static void main(String[] args) {
// 将数字100转换成Integer包装类型(int --> Integer)
Integer x = new Integer(100);
System.out.println(x);// 100
// 将String类型的数字转换成Integer包装类型(String --> Integer)
Integer y = new Integer("123");
System.out.println(y);// 123
// double --> Double
Double d = new Double(123.0);
System.out.println(d);// 123.0
// String --> Double
Double e = new Double("124");
System.out.println(e);// 124.0
}
}
包装类中的常量
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);
}
}
自动装箱和拆箱
package com.bjpowernode.javase.integer;
/**
好消息:在java5之后,引入了一种新特性:自动装箱和自动拆箱
自动装箱:基本数据类型自动转换成包装类。
自动拆箱:包装类自动转换 成基本数据类型。
有了自动拆箱之后,Number类中的方法就用不着了!
自动装箱和自动拆箱的好处:方便编程
*/
public class IntegerTest05 {
public static void main(String[] args) {
// 900是基本数据类型
// x是包装类型
// 基本数据类型 --(自动转换)--> 包装类型:自动装箱
Integer x = 100;
System.out.println(x);// 100
// x是包装类型
// y是基本数据类型
// 包装类型 --(自动转换)--> 基本数据类型:自动拆箱
int y = x;
System.out.println(y);// 100
// z是一个引用,保存的也是对象的内存地址
Integer z = 1000;
// 分析为什么没报错呢?
// z两边是要求是基本数据类型的数字,z是包装类,不属于基本数据类型,这里会进行自动拆箱,将z自动转换成基本数据类型
System.out.println(z + 1);
Integer a = 1000;// Integer a = new Integer(1000) a是引用,保存的是对象内存地址
Integer b = 1000;// Integer b = new Integer(1000) b是引用,保存的是对象内存地址
// == 比较的是对象内存地址,a和b两个引用中保存的对象内存地址是不同的
// == 这个运算符不会触发自动拆箱机制。(只有 + - * / %等运算的时候才会。)
System.out.println(a == b);// false
}
}
Integer面试题
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
}
}
int、Integer、String三种类型之间想换转换
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" 字符串
String s3 = String.valueOf(i1);
System.out.println(s3 + 1);// "1001" 字符串
// int --> Integer
// 自动装箱
Integer x1 = 1000;// 重点
Integer x2 = Integer.valueOf(i1);
// Integer --> int
// 自动拆箱
int y1 = x1;// 重点
int y2 = x2.intValue();
// String --> Integer
Integer k = Integer.valueOf("123");
// Integer --> String
String s4 = String.valueOf(k);
}
}
处理日期
java对日期的处理
package com.bjpowernode.javase.date;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
java中对日期的处理
*/
public class DateTest01 {
public static void main(String[] args) throws Exception{
// 获取系统当前时间(精确到毫秒)
// 直接调用无参数构造方法即可
Date nowTime = new Date();
// Date类已经重写了toString()方法
// System.out.println(nowTime);// Sat Dec 18 11:41:43 CST 2021
// 日期可以格式化吗
// 将日期类型Date,按照制定的格式进行转换:Date --> 转换成具有一定格式的日期字符串 --> String
// SimpleDateFormat是java.text包下的。专门负责日期格式化的。
/*
* yyyy 年(年是4位)
* MM 月(月是2位)
* dd 日
* HH 时
* mm 分
* ss 秒
* SSS 毫秒(毫秒是3位,最高999。1000毫秒代表1秒)
*
* 注意:在日期格式中,除了y M d H m s S这些字符不能随便写之外,剩下的符号格式自己随意组织。
* */
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss SSS");
String nowTimeStr = sdf.format(nowTime);
System.out.println(nowTimeStr);
// 假设现在有一个日期字符串String,怎么转换成Date类型?
// String --> Date
String time = "2008-08-08 08:08:08 888";
// SimpleDateFormat sdf2 = new SimpleDateFormat("格式不能随便写,要和日期字符串相同");
// 注意:字符串的日期格式和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
}
}
统计方法执行时长
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日到系统当前时间的总毫秒数
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);// 1639965003951
// 统计一个方法耗时
// 在调用目标方法之后记录一个毫秒数
long begin = System.currentTimeMillis();
print();
// 在调用目标方法之后记录一个毫秒数
long end = System.currentTimeMillis();
System.out.println("耗费时长" + (end - begin) + "毫秒");
}
// 需求:统计一个方法执行所耗费的时长
public static void print() {
for(int i = 0; i < 1000; i ++) {
System.out.println("i = " + i);
}
}
}
通过毫秒构造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个小时
System.out.println(strTime);// 1970-01-01 08:00:00 001
// 获取昨天的此时的时间。
Date time2 = new Date(System.currentTimeMillis() - 1000*60*60*24L);
String strTime2 = sdf.format(time2);
System.out.println(strTime2);// 2021-12-19 15:43:46 672
// 注意:1000*60*60*24*365已超出int数据类型范围,需要转换成long类型
Date time3 = new Date(System.currentTimeMillis() - 1000*60*60*24*365L);
String strTime3 = sdf.format(time3);
System.out.println(strTime3);// 2020-12-20 15:43:46 672
}
}
数字相关类
数字格式化
package com.bjpowernode.javase.num;
import java.text.DecimalFormat;
/**
关于数字的格式化。(属于了解内容)
*/
public class DecimalFormatTest01 {
public static void main(String[] args) {
// java.text.DecimalFormat专门负责数字格式化的。
// DecimalFormat df = new DecimalFormat("数字格式");
/*
数字格式都有哪些?
# 代表任意数字
, 代表千分位
. 代表小数点
0 代表不够时补0
###,###.##
表示:加入千分位,保留2个小数。
*/
DecimalFormat df = new DecimalFormat("###,###.##");
String s1 = df.format(1234.56);
System.out.println(s1);// "1,234.56"
String s2 = df.format(1234.5678);
System.out.println(s2);// "1,234.57"
DecimalFormat df2 = new DecimalFormat("###,###.0000");// 保留4个小数位,不够补0
String s3 = df2.format(1234.56);
System.out.println(s3);// "1,234.5600"
}
}
高精度BigDecimal
package com.bjpowernode.javase.num;
import java.math.BigDecimal;
/*
1、BigDecimal属于大数据,精度极高。不属于基本数据类型,属于java对象(引用数据类型)
这是java提供的一个类。专门用在财务软件当中。
2、注意:财务软件中double是不够用的。咱们之前有一个学生去用友面试,经理就问了这样一个问题:
你处理过财务数据吗?用的哪一种类型?
千万别说double,说java.math.BigDecimal
* */
public class BigDecimalTest01 {
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 v3 = v1.add(v2);// 调用方法求和
BigDecimal v4 = v1.divide(v2);
System.out.println(v3.toString());// 300
System.out.println(v4);// 0.5
}
}
产生随机数
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
// nextInt翻译为:下一个int类型的数据是101,表示只能到取100
int num2 = random.nextInt(101);// 不包括101
System.out.println(num2);
}
}
随机数相关的题目
package com.bjpowernode.javase.random;
import java.util.Arrays;
import java.util.Random;
/**
编写程序,生成5个不重复的随机数,重复的话重新生成。
最终生成的5个随机数放到数组中,要求数组中这5个随机数不重复。
*/
public class RandomTest02 {
public static void main(String[] args) {
// 创建Random对象
Random random = new Random();
// 创建长度为5的一维数组
int[] arr = new int[5];
// 数组默认值改为-1,防止系统默认值为0时与随机数冲突
for(int i = 0;i < arr.length; i ++) {
arr[i] = -1;
}
int index = 0;
while(index < arr.length) {
//int num = random.nextInt(101);// 随机产生[0-100]
int num = random.nextInt(6);// 随机产生[0-5]
if(!contains(arr,num)) {
arr[index++] = num;
}
}
for(int i = 0; i < arr.length; i ++) {
System.out.println(arr[i]);
}
}
// 创建方法,判断一维数组中是否包含某个数
// 返回true代表包含,返回false代表不包含
public static boolean contains(int[] arr, int key) {
/*(这种方法有bug,原因是排序后数据位置发生变化)
// 对数组先排序
Arrays.sort(arr);
// 对排序后的数组进行二分法查找
int retValue = Arrays.binarySearch(arr, key);
if(retValue >= 0) {
return true;// 包含
}else {
return false;// 不包含
}
*/
for(int i = 0; i < arr.length; i ++) {
if(arr[i] == key) {
return true;
}
}
return false;
}
}
枚举
为什么使用枚举
package com.bjpowernode.javase.enum2;// 标识符,关键字不能做标识符,enum是关键字
/*
这个案例没有使用enum,分析以下程序,在设计方面有什么缺陷?
*/
public class EnumTest01 {
public static void main(String[] args) {
//System.out.println(10 / 0);// java.lang.ArithmeticException: / by zero
// int retValue = divide(10,5);
// System.out.println(retValue == 1? "计算成功":"计算失败");//1
//
// int retValue2 = divide(10,0);
// System.out.println(retValue2 == 1? "计算成功":"计算失败");//0
boolean success = divide(10,0);
System.out.println(success? "计算成功":"计算失败");
}
/*
// 以下程序,计算两个int类型数据的商,计算成功返回1,计算失败返回0
public static int divide(int a, int b) {
try {
int c = a / b;
// 程序执行到此处表示以上代码没有发生异常,表示执行成功
return 1;
}catch(Exception e) {
// 程序执行到此处表示以上程序出现了异常
// 表示执行失败
return 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语言中的枚举类型。
* */
}
枚举的使用
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表示成功,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
}
package com.bjpowernode.javase.enum2;
// 颜色枚举类型
public enum Color {
/*
* 颜色值
* */
RED,BLACK,BLUE,GREEN,YELLOW
}
package com.bjpowernode.javase.enum2;
// 四季枚举类型
public enum Season{
SPRING,SUMMER,AUTUMN,WINTER
}