Math
Math包含执行基本数字运算的方法
思考:没有构造方法,如何使用类中的成员呢? 回答:看类的成员是否都是静态的,如果是,通过类名就可以直接调用
如果类的成员是静态的,那么通过类名就可以直接调用,即不需要构造方法来创建对象 查看帮助文档,搜索Math,如果其软件包为java.lang说明不需要导包。有final关键字就说明是最终类即没有子类。不能实例化就说明不能创建对象, 那不能创建对象如何访问其成员呢,其实Math的成员都被静态修饰了,即不需要创建对象,直接通过类名就可以直接访问
方法名 | 说明 |
---|---|
public static int abs(int a) | 返回参数的绝对值 |
public static double ceil(double a) | 返回大于或等于参数的最小double值,等于一个整数 |
public static double floor(double a) | 返回小于或等于参数的最大double值,等于一个整数 |
public static int round(float a) | 按照四舍五入返回最接近参数的int |
public static int max(int a,int b) | 返回两个int值中的较大值 |
public static int min(int a,int b) | 返回两个int值中的较小值 |
public static double pow(double a,double b) | 返回a的b次幂的值 |
public static double random() | 返回值为double的正值,[0.0,0.1) |
Math的练习
xxxxxxxxxx
package ch12;
public class a_2_1测试 {
public static void main(String[] args) {
//返回参数的绝对值
System.out.println("Math.abs()");
System.out.println(Math.abs(1));
System.out.println(Math.abs(-1));
//返回大于或等于参数的最小double值,等于一个整数。因为返回值是double类型,所以下面输出的是3.0
System.out.println("Math.ceil()");
System.out.println(Math.ceil(2.01));
System.out.println(Math.ceil(2.91));
//返回小于或等于参数的最大double值,等于一个整数。因为返回值是double类型,所以下面输出的是3.0
System.out.println("Math.floor()");
System.out.println(Math.floor(4.01));
System.out.println(Math.floor(4.91));
//按照四舍五入返回最接近参数的int
System.out.println("Math.round()");
System.out.println(Math.round(5.01));
System.out.println(Math.round(5.91));
System.out.println(Math.round(5.45F));
//返回两个int值中的较大值
System.out.println("Math.max()");
System.out.println(Math.max(6,7));
//返回两个int值中的较小值
System.out.println("Math.min()");
System.out.println(Math.min(8,9));
//返回3的2次幂的值
System.out.println("Math.pow()");
System.out.println(Math.pow(3,2));
System.out.println(Math.pow(3.0,2.0));
//返回值为double的正值,[0.0,0.1)的随机数
System.out.println("Math.random()");
System.out.println(Math.random()); //生成小数的随机数
System.out.println(Math.random()*100); //扩大100倍
System.out.println((int)(Math.random()*100)); //生成整数的随机数。原理:强转为int类型。注意这里只能是1~99的随机数
System.out.println((int)(Math.random()*100 + 1)); //生成整数的随机数,且随机数为1~100
}
}
System
System类概述: System包含几个有用的类字段和方法,它不能被实例化(因为System的成员都是被静态修饰的)
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的java虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间,以毫秒为单位 |
System的练习
xxxxxxxxxx
package ch12;
public class a_3_1测试 {
public static void main(String[] args) {
//终止当前运行的java虚拟机,非零表示异常终止
System.out.println("开始");
//System.exit(0); //只输出开始,不输出结束。原理:在这一行已经终止了正在运行的java虚拟机,程序不会再往下执行。先注释,自己解开
System.out.println("结束");
System.out.println("------------------");
//返回当前时间,以毫秒为单位
System.out.println(System.currentTimeMillis()); //当前计算机时间和1970年1月1号0时0分0秒所差的毫秒数。
//思考:怎么计算当前时间和1970年隔了多少年,如下
//毫秒和秒是1000换算单位,秒和分钟是60换算单位,分钟换算为小时要再除以60,再除以24为天,再除以365为年
//为了数据精确可以乘以1.0,让数据变成错浮点数再进行操作
System.out.println(System.currentTimeMillis() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
System.out.println("------------------");
//如何才能知道一个for循环运行耗时的时间,如下
long start = System.currentTimeMillis(); //先记录一个时间
for(int i = 0; i < 1000; i++){
System.out.println(i);
}
}
}
Object类的toString方法
Object类的概述: 没有继承自任何类。类object是类层次结构的根。每个类都有object作为超类。所有对象(包括数组)都实现了这个类的方法
所有类都直接或间接继承object类
object只有一个无参构造方法,即public Object()
思考:为什么子类的构造方法默认访问的是父类的无参构造方法 答案:因为它们的顶级父类只有无参构造方法
方法名 | 说明 |
---|---|
public String toString() | 返回对象的字符串表达形式。建议所有子类(所有类)重写该方法,自动生成 |
toString方法的练习
xxxxxxxxxx
package ch12;
//继承超类,即继承Object类。
public class a_4_1Student extends Object{
//成员变量
private String name;
private int age;
//无参构造方法
public a_4_1Student(){
}
//带参构造方法
public a_4_1Student(String name, int age) {
this.name = name;
this.age = age;
}
//get和set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//同时点击Alt+insert,找到toString,全选里面的子项,点击OK。如下
//这样就重写了Object超类的里面的toString方法。才能正常输出我们写的s对象了
public String toString() {
return "a_4_1Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
xxxxxxxxxx
package ch12;
import java.io.PrintStream;
public class a_4_2测试 {
public static void main(String[] args) {
a_4_1Student s = new a_4_1Student();
s.setName("张三");
s.setAge(18);
System.out.println(s); //输出的却是ch12.a_4_1Student@3b07d329。如何输出我们写的对象呢
//分析上面的原因,首先查找一下println的源码,即选中println,再按Ctrl+B。如下
/*public void println(Object x) { //这里的x就相当于上面我们写的s
String s = String.valueOf(x);
if (getClass() == PrintStream.class) {
// need to apply String.valueOf again since first invocation
// might return null
writeln(String.valueOf(s));
} else {
synchronized (this) {
print(s);
newLine();
}
}
}*/
//继续跟进,查找一下valueOf方法。如下
/*public static String valueOf(Object obj) { //这里的object就相当于上面的x,即s
return (obj == null) ? "null" : obj.toString(); //并且这个表达式结构调用了toString方法
}*/
//继续跟进,查找一下toString方法。如下
/*public String toString() { //返回的是字符串即String类型。总结就是println原理就是使用了Object里面的toString方法
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}*/
//即使这个类不继承Object超类,系统也会默认继承了Object超类。即可以使用Object类里面的方法,比如toString方法。如下
System.out.println(s.toString());
//通过上面演示,我们可以知道默认继承的Object超类里面的toString方法会带来使用上的影响。
//即建议所有Object超类的子类都重写toString方法(注意,几乎所有类都是Object超类的子类,即几乎所有类都建议重写toString方法)
//手动写太麻烦,如何自动生成呢。如下
//同时点击Alt+insert,找到toString,全选里面的子项,点击OK。如下(注意不能再操作类里面这样点击,要去比如a_4_1Student类里面点击)
//此时运行操作类,就正常输出了我们写的s对象类
}
}
Object类的equals方法
方法名 | 说明 |
---|---|
public boolean equals(Object obj) | 比较对象是否相等。默认比较地址值,必须重写才能比较内容,自动生成 |
equals方法的练习
x
package ch12;
public class a_5_1Student {
//成员变量
private String name;
private int age;
//无参构造方法
public a_5_1Student(){
}
//带参构造方法
public a_5_1Student(String name, int age) {
this.name = name;
this.age = age;
}
//get和set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//无法通过直接比较,也直接无法通过equals比较内容是否相同,则需要重写equals方法,如下
//按住Alt+insert,找到equals() and hashCode(),就可以自动重写equals方法
//注意在弹窗中要在Template选项框里面选择'Intelij Default',然后一直点击next,最后点击finish
//如下
public boolean equals(Object o) { //向上转型
if (this == o) return true; //比较地址是否相同,只有同一对象才会地址值相同,如果相同则直接返回true
if (o == null || getClass() != o.getClass()) return false;//如果参数为null或者两个对象来自的不是同一个类(则成员内容一定不同),直接返回false,
a_5_1Student that = (a_5_1Student) o; //把o强转为a_5_1Student类,即向下转型。这行的that代表的是s2
if (age != that.age) return false; //第一个age省略了this。即第一个age是s1的,第二个age是s2的
return name != null ? name.equals(that.name) : that.name == null;
//解释一下上面那行。s1的name不能是空值,s1的内容跟s2的内容进行比较,s2的name不能是空值
}
//下面那部分生成的我们不需要,可以注释或删掉
/*@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}*/
//此时再去测试类里面运行,就可以通过equals比较内容是否相同
}
xxxxxxxxxx
package ch12;
public class a_5_2测试 {
public static void main(String[] args) {
a_5_1Student s1 = new a_5_1Student(); //s1是new出来的,代表的是地址值
s1.setName("李四");
s1.setAge(19);
a_5_1Student s2 = new a_5_1Student(); //s2也是new出来的,代表的是地址值
s2.setName("李四");
s2.setAge(19);
//需求:比较两个对象的内容是否相同
System.out.println(s1 == s2); //通过控制台的输出false,可以发现直接输出是无法比较两个对象的内容是否相同
//不能直接比较是否相等的原理是: s1和s2代表的是地址值,所以就不相等。即上面比较的并不是内容,而是地址值
//思考下面这种'比较两个对象的内容是否相同'的写法,如下
System.out.println(s1.equals(s2)); //equals需要的参数是Object,但我们传的是s2,但是不用担心,s2会自动向上转型
//也是可以发现是无法比较两个对象的内容是否相同
//我们来查看一下上面equals的源码,如下(选中equals,按Ctrl+B)
/*public boolean equals(Object obj) { //把s2当作参数传给obj
return (this == obj); //这个this指的是谁调用equals方法就指向谁,比如这里是指向s1。即这里的this其实是s2
}*/
//上面的equals比较的是地址值,即this == obj。所以我们想要比较内容的话,就必须在a_5_1Student重写equals方法
//此时再去这个测试类里面运行,就可以通过equals比较内容是否相同
}
}