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的练习
xxxxxxxxxxpackage 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的练习
xxxxxxxxxxpackage 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方法的练习
xxxxxxxxxxpackage 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 + '}'; }}xxxxxxxxxxpackage 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比较内容是否相同}xxxxxxxxxxpackage 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比较内容是否相同
}}