Java第十二课. Math&Object
回顾
1.String 的特性:[不变性],值在创建之后不能再修改;
2.StringBuffer 和 StringBuilder:可变的字符串,效率高,以后在拼接字符串的时候,尽量 使用二者(append);单线程用 StringBuilder,线程不安全;多线程的情况下,使用 StringBuffer;
3.方法参数传递:[基本数据类型/String]作为参数传递的是[值的一个副本]给形参,在方法内对形参做操作,不影响实参的值->值传递;
[数组,类引用类型]作为参数传递的是引用名的值其实是[堆的地址]给形参,则实参和形参2个引用名指向堆中的同一个对象,在方法体中堆改地址中的值改变就会影响实参;
1. 可变参数
Java1.5增加了可变参数特性,适用于参数个数不确定,类型确定的情况
1.1 可变参数的特点
1.2 语法格式:int… pa
pa[1]
public class Test01 {
/**
* 可变参数
* ...表示可变参数,本质上是一个数组,可以传递0到N个参数
* 一个方法只能有以一个可变参数,只能定义在参数列表的最后
* @param params
*/
public static void test(int... params) {//int[] params
//传递进来的参数
for (int i = 0; i < params.length; i++) {
System.out.print(params[i]);
}
System.out.println();
}
public static void main(String[] args) {
//可变参数,可以传递不同个数的参数
test();
test(10);
test(10,20);
test(100,200,300);
}
}
输出结果:
10
1020
100200300
2.方法的参数传递
2.1 可变参数作为参数
2.11 基本数据类型作为参数【值传递】
public static void test01(int... params) {//int[] params
//传递进来的参数
for (int i = 0; i < params.length; i++) {
//改变参数的值
params[i]=params[i]+1;
System.out.print("test01:"+params[i]+" ");
}
}
测试类:
System.out.println("--------可变参数作为参数传递 基本数据类型 值传递---------");
int i=1,j=3,k=6;
test01(i,j,k);
System.out.println("main中:"+i+","+j+","+k);
输出结果:
--------可变参数作为参数传递 基本数据类型 值传递---------
test01:2 test01:4 test01:7 main中:1,3,6
2.12 String可变参数作为传递【值传递】
public static void test02(String... params) {
//传递进来的参数
for (int i = 0; i < params.length; i++) {
//改变参数的值
params[i]=params[i]+"@";
System.out.print("test02:"+params[i]+" ");
}
}
测试类:
System.out.println("--------可变参数作为参数传递 String数据类型 值传递---------");
String s1="a";
String s2="b";
String s3="c";
test02(s1,s2,s3);
System.out.println("main:s1="+s1+",s2="+s2+",s3="+s3);
输出结果:
--------可变参数作为参数传递 String数据类型 值传递---------
test02:a@ test02:b@ test02:c@ main:s1=a,s2=b,s3=c
2.13 类可变参数作为传递【引用传递】
public static void test03(Dog... params) {
//传递进来的参数
for (int i = 0; i < params.length; i++) {
params[i].setName("小黑");
System.out.print("test03:"+params[i].getName()+" ");
}
}
测试类:
System.out.println("--------可变参数作为参数传递 引用数据类型 引用传递---------");
Dog dog=new Dog();
Dog dog2=new Dog();
dog.setName("小白");
dog2.setName("小红帽");
test03(dog,dog2);
System.out.println("main:dog="+dog.getName()+",dog2="+dog2.getName());
输出结果:
test03:小黑 test03:小黑 main:dog=小黑,dog2=小黑
可变参数作为参数,到底是如何传递要取决于可变参数的数据类型。
2.2总结:值传递与引用传递
[值传递]:
(形式参数类型是基本数据类型):
方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。
[引用传递]
(形式参数类型是引用数据类型参数):
也称为传地址。方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。
3. Math
3.1 常见方法
• Math类位于java.lang包中,是一个 final 类,不能被继承;
• Math类中所有方法都是 static 方法,可以直接使用类名Math调用;
• Math中定义了大量与数学运算有关的方法,包括求绝对值、三角函数、平方根
等;
字段摘要 | |
---|---|
static double | E 比任何其他值都更接近 e(即自然对数的底数)的 double 值。 |
**static ** double | PI 比任何其他值都更接近 pi(即圆的周长与直径之比)的 double 值。 |
常见的方法:
static double | floor(double a) 返回最小的(最接近负无穷大)double 值,该值大于等于参数,并等于某个整数。 |
---|---|
static double | ceil(double a) 返回最大的(最接近正无穷大)double 值,该值小于等于参数,并等于某个整数。 |
static long | round(double a) 返回最接近参数的 long。 |
static double | random() 返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。 |
求随机数:取值范围0~1 ,1取不到
public class TestMath {
public static void main(String[] args) {
//使用Math类中的属性和方法
System.out.println(Math.PI);
//计算圆的面积
int r=5;
System.out.println(Math.PI*r*r);
//pow(r,2)次幂
System.out.println(Math.PI* Math.pow(r, 2));
//1.获取随机数 random() 返回值为 double值为正号,大于等于 0.0 ,小于 1.0 。
//[0,1)
double i=Math.random();
System.out.println(i);
//[0,3)
int i2=(int)(Math.random()*3);
System.out.println(i2);
//[0,3]
int i3=(int)(Math.random()*4);
System.out.println(i3);
//[1,3]
int i4=(int)(Math.random()*3+1);
System.out.println(i4);
//2.取整 floor:地板
System.out.println("Math.floor 向下取整 -往小的数取整");
System.out.println(Math.floor(11.1));//11.0
System.out.println(Math.floor(11.8));//11.0
System.out.println(Math.floor(-12.1));//-13.0
System.out.println(Math.floor(-12.9));//-13.0
//ceil 天花板
System.out.println("Math.ceil 向上取整-往大的数");
System.out.println(Math.ceil(11.5));//12.0
System.out.println(Math.ceil(12.9));//13.0
System.out.println(Math.ceil(-12.1));//-12.0
System.out.println(Math.ceil(-12.9));//-12.0
System.out.println("Math.round 四舍五入");
System.out.println(Math.round(11.5));//12
System.out.println(Math.round(11.8));//12
System.out.println(Math.round(11.1));//11
System.out.println(Math.round(-12.1));//-12
System.out.println(Math.round(-12.5));//-12
System.out.println(Math.round(-1.5));//-1
}
}
3.2 Java中的大整数API使用
• Java中整数最大范围是 long 型,64 位,如果需要使用超过 long 范围的大整数,可以使用BigInteger类;
• BigInteger位于java.math包中,定义了一系列的数学运算方法,调用这些方法可以进行计算,不能使用运算符计算;
public static void main(String[] args) {
// 使用字符串表示超出范围的大整数
String s1="29219291291919391912919283232323";
String s2="2007594379874134134134127943";
// 将字符串作为参数,创建大整数BigInteger对象
BigInteger bi1=new BigInteger(s1);
BigInteger bi2=new BigInteger(s2);
// 调用BigInteger类中的方法进行运算,下面是加法和除法
System.out.println(bi1.add(bi2));
System.out.println(bi1.divide(bi2));
}
步骤1:将超出范围的整数用String声明;
步骤2:将字符串包装成BigInteger对象
步骤3:调用BigInteger类的方法,进行数学运算
• java.math包中还有一个类叫BigDecimal,是用来针对浮点型进行精确运算的;需要精确计算的时候使用,一般用于商业运算;
//使用double类型进行运算
double d1=4.3;
double d2=5.8;
System.out.println(d1+d2);
// 使用BigDecimal类型进行运算
BigDecimal bd1=new BigDecimal(d1);
BigDecimal bd2=new BigDecimal(d2);
System.out.println(bd1.add(bd2));
BigInteger实现原理解析:
• 为了表达超过 long 型数据范围的超大型整数,可以借助数字字符串+按位(10进制位)运算的方式;
• 最容易理解的办法是将直接保存字符串数组用于描述长整数的字面值(需要注意的是,JDK内置的长整数类型采用的是效率更高的2进制保存方法);
• 在对两个大整数进行四则运算时,获取每一位对应的数值(利用字符串API很容易获取)按照规则计算即可(需要记忆进位和借位);
• 大整数除法可以使用减法模拟,但是效率极低(可以使用先减去除数n倍的方式优化);
3.3 简单的模拟彩票生成器
[问题]:36选7,1到36个球,每次产生一个,一共产生7个号码,不能重复;
产生 1~36数字:
提示:生成1~36的随机数:(int)(Math.radom()*36+1)
public class TestRandom {
public static void main(String[] args) {
// 定义一个数组存储随机数 1~36选7个数字->随机生成
int array[]=new int[7];
//使用Random类
Random random=new Random();
//随机产生7个数
for (int i = 0; i < array.length; i++) {
//产生一个随机数后就放到数组中
//随机生成1~36这个范围内的数字
//array[i]=(int)(Math.random()*36+1);
array[i]=random.nextInt(36)+1;
//但是要判断这个数array[i]和之前产生的元素是否重复
//当i=0不用判断
//当i=1,要跟array[0]
//当i=2,要跟array[0],array[1]
//...
//当i=6,要跟array[0],array[1]....array[5]
for (int j = 0; j < i; j++) {
if (array[i]==array[j]) {
//和之前的数比较重复,break->不用比了,这个产生的数要作废,i--,重新生成
i--;
break;
}
}
}
System.out.println("数组的值:");
for (int i : array) {
System.out.print(i+" ");
}
}
}
[注意]:这里 break 跳出当前循环时生成的随机数并没有销毁,i--后重新开始这次循环覆盖了这个值;
4. Random类
• Math类中的random()方法可以产生随机数,上节演示过。然而,该方法只能生
成[0.0,1.0)范围的 double 值;很多时候,可能需要生成不同类型不同范围的随机值;
• java.util包中的 Random类可以用来生成不同类型的随机值,功能更为强大;
构造方法摘要 |
---|
Random() 创建一个新的随机数生成器 |
Random(long seed) 使用一个种子参数创建Random对象,参数相同的Random对象,每次生成的 随机数相同。 |
• Random类有两个构造方法,无参的构造方法创建对象后,每次
都生成不同的随机数;有参的构造方法创建对象后,如果种子参
数值一样,那么每次生成的随机数也相同;
• Random类功能强大,能生成int,float,double,boolean各种类型
的随机数;
• nextInt生成不定范围的 int 随机数,而带参数的nextInt生成的随机
数有范围;
4.1 直接使用nextInt()指定特定范围的值,不用再自己*多少
int nextInt(int n)
返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
4.2 【面试题】Math类中的取整三个函数
取整函数(ceil(向上取整)、floor(向下取整)、round(四舍五入))
4.3 【面试题】Java 中的 Math. round(-1. 5) 等于多少?
等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。
5. Object类
类 Object
是类层次结构的根类。每个类都使用 Object
作为超类。所有对象(包括数组)都实现这个类的方法。
5.1 重写父类的toString()、equals()方法
1. toString():返回的是类名+@+哈希地址(唯一特定的地址)。通常,ToString方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。
Object中的toString()方法:
重写:
快捷键: Ctrl+o 列出类的所有方法
2. equals()用于判断两个对象是否相等;
Object中的equals()方法:
重写父类的equals():
public static void main(String[] args) {
Person person=new Person("001","张三", "男", 22);
Person person2=new Person("001","张三", "男", 22);
System.out.println(person.equals(person2));//true
System.out.println(person);
}
输出结果:
true
Person [sno=001, name=张三, sex=男, age=22]
5.2 练习:
定义一个员工类,属性:编号,姓名,学历,岗位
实现以下功能: 1、能够根据编号判断是否是同一个员工
2、重写toString()方法,显示出 姓名:xxx,学历:本科,岗位:高级工程师
主要目的:equals和toString重写
public class Staff {
//员工属性
private String sno;
private String sname;
private String sedu;
private String spost;
//封装
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSedu() {
return sedu;
}
public void setSedu(String sedu) {
this.sedu = sedu;
}
public String getSpost() {
return spost;
}
public void setSpost(String spost) {
this.spost = spost;
}
//构造方法
public Staff(String sno, String sname, String sedu, String spost) {
super();
this.sno = sno;
this.sname = sname;
this.sedu = sedu;
this.spost = spost;
}
public Staff() {
}
@Override
public String toString() {
return "Staff [sno=" + sno + ", sname=" + sname + ", sedu=" + sedu + ", spost=" + spost + "]";
}
@Override
public boolean equals(Object obj) {
Staff staff=(Staff)obj;
if (this.sno.equals(staff.sno)) {
return true;
}
return false;
}
}
public class TestStaff {
public static void main(String[] args) {
Staff staff=new Staff("001", "张三", "本科", "高级");
Staff staff1=new Staff("001", "张三", "本科", "高级");
System.out.println(staff);
System.out.println(staff.equals(staff1));//true
}
}
Staff [sno=001, sname=张三, sedu=本科, spost=高级]
true
5.3 hashCode
hashCode()被设计是用来使得哈希容器能高效的工作,相当于每个对象的身份证号码。
hashCode是java.lang.Object.hashCode() 或者 java.lang.System.identityHashCode(obj) 会返回的值。他是一个对象的身份标识。官方称呼为:标识哈希码( identity hash code)
hashCode()这个方法是Java根类Object的方法,因此所有继承自Object类的子类的对象都可以调用该方法计算出本对象的哈希值,默认实现是根据对象的内存地址进行计算。
[面试题] 子类中可以重写父类的哪些方法?
Alt+/
5.4 finalize()
● Java和C + +不同,没有提供析构方法
● Object 中包含了一个叫做 finalize()的方法,提供在对象被回收时调用以释放资源,默认情况下其不执行任何动作;
● 由于 Object 是Java继承体系的根,因此事实上所有的Java类都具备finalize方法;
● 当垃圾回收器确定了一个对象没有任何引用时,其会调用 finalize()方法。 但是,[finalize方法并不保证调用时机,因此也不建议重写 finalize()方法];
●如果必须要重写 finalize()方法, 请记住使用 super.finalize()调用父类的清除方法,否则对象清理的过程可能不完整;
public class Dog {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dog(String name) {
super();
this.name = name;
}
public Dog() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Dog [name=" + name + "]";
}
@Override
protected void finalize() throws Throwable {
System.out.println("Dog被垃圾回收器回收");
super.finalize();//这边调用父类的,到时候谁会调它,jvm会调
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Dog dog=new Dog("哈士奇");
System.out.println(dog);
}
//运行垃圾回收器
System.gc();
}
}
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog [name=哈士奇]
Dog被垃圾回收器回收
Dog被垃圾回收器回收
Dog被垃圾回收器回收
Dog被垃圾回收器回收
Dog被垃圾回收器回收
Dog被垃圾回收器回收
Dog被垃圾回收器回收
【面试题】final finalize() finally有什么不同?
回答出每个关键字或方法的应用场景即可;
5.41 finalize的特点
1. finalize()每个对象都有;
2. finalize()不需要程序员去调用,由java虚拟机(JVM)自动调用;
3. Java对象如果没有更多的引用去指向它,则该java对象成为垃圾数据,等待垃圾回收器的回收,垃圾回收器在回收这个java对象就会自动调用该对象的finalize();
5.5 Object克隆的方法(了解)
使用clone的方法时候,要保证我们的那个对象对应的类,实现了Cloneable的接口才行;
5.51 浅克隆:
public class Boy implements Cloneable{
private String name;
//拥有女朋友对象
private Girl girl;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Girl getGirl() {
return girl;
}
public void setGirl(Girl girl) {
this.girl = girl;
}
public Boy(String name, Girl girl) {
super();
this.name = name;
this.girl = girl;
}
public Boy() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Boy [name=" + name + ", girl=" + girl + "]";
}
//克隆:被克隆的类必须满足1:实现Cloneable接口 2.重写clone()
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class Girl{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Girl(String name) {
super();
this.name = name;
}
public Girl() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Girl [name=" + name + "]";
}
}
测试类:
public class TestBoy {
public static void main(String[] args) throws CloneNotSupportedException {
/*Girl girl=new Girl("静静");
Boy boy=new Boy("张三", girl);*/
Boy boy=new Boy();
boy.setName("张三");
Girl girl=new Girl();
girl.setName("静静");
boy.setGirl(girl);
System.out.println("原生:"+boy.hashCode()+"girl对象:"+boy.getGirl().hashCode());
Boy boy2=(Boy)boy.clone();
boy2.setName("李四");
boy2.getGirl().setName("菁菁");
System.out.println("克隆后:"+boy2.hashCode()+"girl对象:"+boy2.getGirl().hashCode());
}
}
以上称为浅克隆,看到的结果,Boy中引用了一个Girl,当girl的某个属性修改的的时候,每个boy对象中的girl信息都是一致的;
我们的想法一定是希望修改了某个boy属性girl的name的时候,其他的boy对象的girl属性不变;
5.52 深克隆:
public class Boy2 implements Cloneable{
private String name;
//拥有女朋友对象
private Girl2 girl;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Girl2 getGirl() {
return girl;
}
public void setGirl(Girl2 girl) {
this.girl = girl;
}
public Boy2(String name, Girl2 girl) {
super();
this.name = name;
this.girl = girl;
}
public Boy2() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Boy [name=" + name + ", girl=" + girl + "]";
}
//克隆:被克隆的类必须满足1:实现Cloneable接口 2.重写clone()
@Override
protected Object clone() throws CloneNotSupportedException {
// 深克隆,除了克隆自己本身,还需要克隆boy对象中包含的girl对象
//1.先克隆一个boy对象
Boy2 boy2=(Boy2)super.clone();
//2.把girl对象也克隆
Girl2 girl2=(Girl2)boy2.getGirl().clone();
//3.对克隆出来boy对象设置一个新的girl对象
boy2.setGirl(girl2);
return boy2;
}
}
public class Girl2 implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Girl2(String name) {
super();
this.name = name;
}
public Girl2() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Girl [name=" + name + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
测试类:
public class TestBoy2 {
public static void main(String[] args) throws CloneNotSupportedException {
Girl2 girl=new Girl2("静静");
Boy2 boy=new Boy2("张三", girl);
System.out.println("原生:"+boy.hashCode()+"girl对象:"+girl.hashCode());
Boy2 boy2=(Boy2)boy.clone();
boy2.setName("李四");
boy2.getGirl().setName("菁菁");
System.out.println("克隆后:"+boy2.hashCode()+"girl对象:"+boy2.getGirl().hashCode());
}
}
5.53【面试题】谈谈Java的克隆?
[浅克隆]:
"创建一个新对象,新对象的属性和原来对象完全相同,对于引用的其他对象属性,仍指向原有属性所指向的对象的内存地址"。
(例如:Boy类中有一个Girl数据类型的对象属性,浅克隆的时候不会克隆该Girl对象,而是所有的Boy类的对象共享同一个Girl实例。)
[深克隆]:
"创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址"。
(例如:Boy类中有一个Girl数据类型的对象属性,深克隆表示同时也会克隆该Girl对象,每一个Boy类的对象都各自拥有一个Girl实例。)
总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。
[用处]:当你的对象要求为不可变的时候,在传对象的时候,可以考虑clone。例如方法的参数传递,传递对象的时候是引用传递,如果不希望改变原始对象的数据,则就可以使用克隆。
6. JDK API 工具包
6.1 Java.util.Date
操作日期时间类:
操作日期和时间,只需要掌握获取当前系统日期时间方法;
public class TestDate {
public static void main(String[] args) {
// 掌握如何获取当前系统时间
Date date=new Date();
System.out.println(date);
System.out.println(date.toLocaleString());//格式化输出
System.out.println(date.getDate());
System.out.println(date.getMonth());//月份从0~11,0表示1月
}
}
Sun Dec 13 13:32:23 CST 2020
2020-12-13 13:32:23
13
11
6.2 Java.util.Calendar
推荐使用的日期时间类
public class TestCalendar {
public static void main(String[] args) {
//Calendar c=new Calendar();//报错,按F3进去看源码,是一个抽象类,不能直接实例化
//Calendar 的 getInstance 方法返回一个 Calendar 对象
Calendar calendar=Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR));//2020
System.out.println(calendar.get(Calendar.MONTH)+1);//获取月份记得+1 ,因为是从0代表1月
System.out.println(calendar.get(Calendar.DATE));//10
//星期几
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));//星期四 5,一周7天从周日开始的
//获取该月最大天数
System.out.println(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
//设置未来时间
calendar.set(Calendar.YEAR, 2022);
calendar.set(Calendar.MONTH, 10);//显示11月,第一个月=0
calendar.set(Calendar.DATE, 1);
System.out.print(calendar.get(Calendar.YEAR)+"年");//2020
System.out.print(calendar.get(Calendar.MONTH)+1+"月");//获取月份记得+1 ,因为是从0代表1月
System.out.print(calendar.get(Calendar.DATE)+"日");//10
}
}
6.3 问题:Date和Calendar是否可以转换?
public class TestCanlendar2 {
public static void main(String[] args) {
// Date与Calendar相互装换
//1.Calendar转换成 Date Calendar的getTime()
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
//2.Date转成Calendar Calendar的setTime()
Date date2 = new Date();
Calendar.getInstance().setTime(date2);
}
}
6.4 SimpleDateFormat(辅助):
对日期时间进行格式化输出:
日期和时间模式 结果 “yyyy.MM.dd G ‘at’ HH:mm:ss z” 2001.07.04 AD at 12:08:56 PDT “EEE, MMM d, ''yy” Wed, Jul 4, '01 “h:mm a” 12:08 PM “hh ‘o’‘clock’ a, zzzz” 12 o’clock PM, Pacific Daylight Time “K:mm a, z” 0:08 PM, PDT “yyyyy.MMMMM.dd GGG hh:mm aaa” 02001.July.04 AD 12:08 PM “EEE, d MMM yyyy HH:mm:ss Z” Wed, 4 Jul 2001 12:08:56 -0700 “yyMMddHHmmssZ” 010704120856-0700 "yyyy-MM-dd’T’HH:mm:ss.SSSZ" 2001-07-04T12:08:56.235-0700
yyyy年 MM月dd日 HH:mm:ss
上面加粗的是格式,不能乱写,根据下面格式表写的,没有加粗的字体是用户随意选择要显示的格式
public class TestSimpleDateFormat {
public static void main(String[] args) throws ParseException {
// 获取当前系统时间
Date date=new Date();
System.out.println(date.toLocaleString());
//格式:2020年12月11日 10时50分30秒
//1.借助辅助类SimpleDateFormat
SimpleDateFormat s=new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 ");//自己规定格式但是注意大小写
//2.format(date)将日期带有日期格式的字符串类型
String string=s.format(date);
System.out.println(string);
//parse(String text) 解析字符串的文本,生成 Date。
Date date2=s.parse(string);
System.out.println(date2.toLocaleString());
}
}
2020-12-13 14:24:00
2020年12月13日 14时24分00秒
2020-12-13 14:24:00
7. 练习
1. 随机数:
/**
* 1.随机数:猜数字游戏 【1-10】Math.random() Random类
* @author Administrator
*
*/
public class Test01 {
public static void main(String[] args) {
System.out.println("请输入1~10以内的数字:");
Scanner scanner=new Scanner(System.in);
int num=scanner.nextInt();
//int pcNum=getRandom();
int pcNum=getRandom2();
System.out.println("电脑随机数:"+pcNum);
if (num==pcNum) {
System.out.println("中奖了~");
}else {
System.out.println("谢谢惠顾");
}
scanner.close();
}
/**
* 专门用来产生1~10以内的随机数
* 1.使用Math类
*/
public static int getRandom() {
return (int)(Math.random()*10+1);
}
/**
* 专门用来产生1~10以内的随机数
* 1.使用Random类
*/
public static int getRandom2() {
Random random=new Random();
int num=random.nextInt(10)+1;
return num;
}
}
2. 彩票生成器
/**
* 2.彩票生成器:先将1-36这些数字存在数组中,随机产生(10000次)一些数字(数组下标),交换数组元素的位置
//从而达到把数组中的元素的顺序打乱
//最后从数组中取前7个数
* @author Administrator
*
*/
public class Test02 {
public static void main(String[] args) {
// 1.先将1-36这些数字存在数组中
int arr[]=new int[36];
for (int i = 0; i < arr.length; i++) {
arr[i]=i+1;
}
//随机产生(10000次)一些数字(数组下标)
for (int i = 0; i < 10000; i++) {
//1.一次生成2个随机数->当成数组下标
int index1=(int)(Math.random()*36) ; //[0~35] arr[7]=8
int index2=(int)(Math.random()*36) ; //[0~35] arr[17]=18
//2.交换这些随机数对应的位置上的数
int t;
t=arr[index1];
arr[index1]=arr[index2];
arr[index2]=t;
}
System.out.println("--------7个随机数------");
for (int i = 0; i < 7; i++) {
System.out.print(arr[i]+" ");
}
}
}
3. 综合作业
从控制台输入一个时间值:格式自定义,建议格式:2020-12,然后根据用户的输入,我们打印这个月的日历出来
要解决的问题:
1. 从控制台输入进来的字符串,如何转换成 Date(Calandar)格式.可以SimpleDateFormat把Date转Calandar
2. 如何确定这个月有几天,并打印出来
3. 确定这个月的第一天是周几
public class Test03 {
public static void main(String[] args) throws ParseException {
String input_date=inputDate();
Calendar calendar=converCalendar(input_date);
printDate(calendar) ;
}
/**
* 1.输入时间
* @return 输入的时间
*/
public static String inputDate() {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入年份和月份:(eg:2020-09)");
String input_date=scanner.nextLine();
return input_date;
}
/**
* 2.将字符串转成Calendar
* @param 输入的时间
* @return Calendar对象
* @throws ParseException
*/
public static Calendar converCalendar(String input_date) throws ParseException {
//1.要注意,input_date是一个字符串
//能不能将String->Date->Calendar?
SimpleDateFormat s=new SimpleDateFormat("yyyy-MM");
//parse()将字符串转成Date
Date date=s.parse(input_date);
//Date->Calendar?
Calendar calendar=Calendar.getInstance();
//setTime()将Date->Calendar
calendar.setTime(date);
return calendar;
}
/**
* 3.打印功能
* @param calendar对象
*/
public static void printDate(Calendar calendar) {
//这个月有几天
int days=calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
//System.out.println("这个月有"+days+"天");
//确定该月的第一天是周几
int weekday=calendar.get(Calendar.DAY_OF_WEEK);
//System.out.println("这个月的第一天是一周的第几天:"+weekday);//周日是1
//打印星期头格式
System.out.println("日\t一\t二\t三\t四\t五\t六");
//打印空格(制表符\t)
for (int i = 1; i < weekday; i++) {
System.out.print("\t");
}
//打印这个月的每一天
for (int i = 1; i <= days; i++) {
System.out.print(i+"\t");
calendar.set(Calendar.DAY_OF_MONTH, i);
int weekday2=calendar.get(Calendar.DAY_OF_WEEK);
//换行的条件 只要是周六就换行
if (weekday2==7) {
System.out.println();
}
}
}
}
请输入年份和月份:(eg:2020-09)
2020-12-13
日 一 二 三 四 五 六
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
8. 总结
1. 方法的参数传递: String: 值传递;
2. 可变参数: 不确定参数个数用可变参数作为参数,[语法:数据类型...参数名]
特点1: 方法定义时只能写一个可变参数; 2. 放最后;
3. 可变参数作为参数传递: 主要是由[参数类型]决定是值传递还是引用传递;
4. 方法中,引用名出现=指向发生变化,与原本地址上的内容无关,不会修改内容;
5. Math: Math.属性/方法() 3个取整的方法 random()
6. Random类: 生成随机数:nextInt(n)范围:0~n,n取不到
7.Object:所有类的超类,toString equals 重写的方法
8.克隆:
浅克隆 2个前提:1.实现克隆接口 2. 重写clone方法
浅克隆:只能克隆对象本身;
深克隆:克隆对象本身+克隆包含的对象