1、多态
同类型的对象,执行同一个行为,会表现出不同的行为特征。
多态的常见形式
父类类型 对象名称 = new 子类构造器;
接口 对象名称 = new 实现类构造器;
多态中成员访问特点
方法调用:编译看左边,运行看右边。变量调用:编译看左边,运行也看左边。( 多态侧重行为多态 )多态的前提
有继承/实现关系;有父类引用指向子类对象;有方法重写。
/** 父类 */ public class Animal { public String name = "动物名称"; public void run(){ System.out.println("动物可以跑~~"); } }
public class Dog extends Animal{ public String name = "狗名称"; @Override public void run() { System.out.println("🐕跑的贼溜~~~~~"); } }
public class Tortoise extends Animal{ public String name = "乌龟名称"; @Override public void run() { System.out.println("🐢跑的非常慢~~~"); } }
public class Test { public static void main(String[] args) { // 目标:先认识多态的形式 // 父类 对象名称 = new 子类构造器(); Animal a = new Dog(); a.run(); // 方法调用:编译看左,运行看右 System.out.println(a.name); // 方法调用:编译看左,运行也看左,动物名称 Animal a1 = new Dog(); a1.run(); System.out.println(a1.name); // 动物名称 } }
多态优势:
在多态形式下,右边对象可以实现解耦合,便于扩展和维护。Animal a = new Dog();
a.run(); // 后续业务行为随对象而变,后续代码无需修改
定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。
/** 父类 */ public class Animal { public String name = "动物名称"; public void run(){ System.out.println("动物可以跑~~"); } }
public class Tortoise extends Animal { public String name = "乌龟名称"; @Override public void run() { System.out.println("🐢跑的非常慢~~~"); } }
public class Dog extends Animal { public String name = "狗名称"; @Override public void run() { System.out.println("🐕跑的贼溜~~~~~"); } /** 独有功能 */ public void lookDoor(){ System.out.println("🐕在看🚪!!!"); } }
public class Test { public static void main(String[] args) { Animal d = new Dog(); go(d); // d.lookDoor(); 多态下不能访问子类独有功能 Animal t = new Tortoise(); go(t); } /** 希望这个方法可以接收一切子类动物对象 * @param a */ public static void go(Animal a){ System.out.println("预备~~~"); a.run(); System.out.println("结束~~~~"); } }
多态下引用数据类型的类型转换
自动类型转换(从子到父):子类对象赋值给父类类型的变量指向。
强制类型转换吗(从父到子)
此时必须进行强制类型转换:子类 对象变量 = ( 子类 ) 父类类型的变量作用:可以解决多态下的劣势,可以实现调用子类独有的功能。注意 : 如果 转型后的 类型 和 对象真实类型 不是同一种类型 ,那么在转换的时候就会出现 ClassCastExceptionAnimal t = new Tortoise();
Dog d = (Dog)t; // 出现异常 ClassCastException
Java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换
变量名 instanceof 真实类型
判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之
/** 父类 */ public class Animal { public String name = "动物名称"; public void run(){ System.out.println("动物可以跑~~"); } }
public class Dog extends Animal { public String name = "狗名称"; @Override public void run() { System.out.println("🐕跑的贼溜~~~~~"); } /** 独有功能 */ public void lookDoor(){ System.out.println("🐕在看🚪!!!"); } }
public class Tortoise extends Animal { public String name = "乌龟名称"; @Override public void run() { System.out.println("🐢跑的非常慢~~~"); } /** 独有功能 */ public void layEggs(){ System.out.println("🐢在下蛋~~~"); } }
/** 目标:学习多态形式下的类中转换机制。 */ public class Test { public static void main(String[] args) { // 自动类型转换 Animal a = new Dog(); a.run(); // a.lookDoor(); // 多态下无法调用子类独有功能 // 强制类型转换:可以实现调用子类独有功能的 Dog d = (Dog) a; d.lookDoor(); // 注意:多态下直接强制类型转换,可能出现类型转换异常 // 规定:有继承或者实现关系的2个类型就可以强制类型转换,运行时可能出现问题。 // Tortoise t1 = (Tortoise) a; // 建议强制转换前,先判断变量指向对象的真实类型,再强制类型转换。 if(a instanceof Tortoise){ Tortoise t = (Tortoise) a; t.layEggs(); }else if(a instanceof Dog){ Dog d1 = (Dog) a; d1.lookDoor(); } System.out.println("---------------------"); Animal a1 = new Dog(); go(a1); } public static void go(Animal a){ System.out.println("预备~~~"); a.run(); // 独有功能 if(a instanceof Tortoise){ Tortoise t = (Tortoise) a; t.layEggs(); }else if(a instanceof Dog){ Dog d1 = (Dog) a; d1.lookDoor(); } System.out.println("结束~~~~"); } }
多态案例:
需求:
使用面向对象编程模拟:设计一个电脑对象,可以安装 2 个 USB 设备鼠标:被安装时可以完成接入、调用点击功能、拔出功能。键盘:被安装时可以完成接入、调用打字功能、拔出功能。分析:
① 定义一个 USB 的接口(申明 USB 设备的规范必须是:可以接入和拔出)。② 提供 2 个 USB 实现类代表鼠标和键盘,让其实现 USB 接口,并分别定义独有功能。③ 创建电脑对象,创建 2 个 USB 实现类对象,分别安装到电脑中并触发功能的执行。public interface USB { void connect(); void unconnect(); }
/** 实现类(子类) */ public class KeyBoard implements USB{ private String name; public KeyBoard(String name) { this.name = name; } @Override public void connect() { System.out.println(name + "成功的接入了设备了~~~"); } @Override public void unconnect() { System.out.println(name + "成功的从设备弹出了~~~"); } /** 独有功能 */ public void keyDown(){ System.out.println(name + "写下了:老铁,6666,下次再来哦,老弟~~~~"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
/** 实现类(子类) */ public class Mouse implements USB{ private String name; public Mouse(String name) { this.name = name; } @Override public void connect() { System.out.println(name + "成功的接入了设备了~~~"); } @Override public void unconnect() { System.out.println(name + "成功的从设备弹出了~~~"); } /** 独有功能 */ public void click(){ System.out.println(name + "双击点亮小红心~~~~"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Computer { /** 提供一个安装的入口:行为。 */ public void installUSB(USB u){ u.connect(); // 独有功能 if(u instanceof Mouse){ Mouse m = (Mouse) u; m.click(); }else if(u instanceof KeyBoard) { KeyBoard k = (KeyBoard) u; k.keyDown(); } u.unconnect(); } }
/** 目标:USB设备模拟 1、定义USB接口:接入 拔出 2、定义2个USB的实现类:鼠标、键盘。 3、创建一个电脑对象,创建USB设备对象,安装启动。 */ public class Test { public static void main(String[] args) { // a、创建电脑对象 Computer c = new Computer(); // b、创建USB设备对象 USB u = new Mouse("罗技鼠标"); c.installUSB(u); USB k = new KeyBoard("双飞燕键盘"); c.installUSB(k); } }
2、 内部类
内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)
public class People{
// 内部类
public class Heart{
}
}内部类的使用场景、作用
①当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计。② 内部类通常可以方便访问外部类的成员,包括私有的成员。③内部类提供了更好的封装性,内部类本身就可以用private protectecd 等修饰,封装性可以做更多控制。
静态内部类:
有 static 修饰, 属于外部类本身。它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已。public class Outer{
// 静态成员内部类
public static class Inner{
}
}静态内部类创建对象的格式:
格式:外部类名.内部类名 对象名 = new 外部类名.内部类构造器;
Outer.Inner in = new Outer.Inner();
/** 外部类 */ public class Outer { public static int a = 100; private String hobby; /** 学习静态成员内部类 */ public static class Inner{ private String name; private int age; public static String schoolName; public Inner(){} public Inner(String name, int age) { this.name = name; this.age = age; } public void show(){ System.out.println("名称:" + name); System.out.println(a); // System.out.println(hobby); // 报错! // Outer o = new Outer(); // System.out.println(o.hobby); } 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; } } }
public class Test { public static void main(String[] args) { Outer.Inner in = new Outer.Inner(); in.setName("张三"); in.show(); } }
1、静态内部类中是否可以直接访问外部类的静态成员?
可以,外部类的静态成员只有一份可以被共享访问。2、静态内部类中是否可以直接访问外部类的实例成员?
不可以的,外部类的实例成员必须用外部类对象访问。
成员内部类:
无 static 修饰, 属于外部类的对象。JDK16 之前,成员内部类中不能定义静态成员, JDK 16 开始也可以定义静态成员了。public class Outer {
// 成员内部类
public class Inner {
}
}成员内部类创建对象的格式:
格式:外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();
Outer.Inner in = new Outer().new Inner();/** 外部类 */ public class Outer { public static int num = 111; private String hobby; public Outer() { } public Outer(String hobby) { this.hobby = hobby; } /** 成员内部类:不能加static修饰 属于外部类对象的 */ public class Inner{ private String name; private int age; public static int a = 100; // JDK 16开始支持静态成员了 public static void test(){ System.out.println(a); } public void show(){ System.out.println("名称:" + name); System.out.println("数量:" + num); System.out.println("爱好:" + hobby); } 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; } } }
public class Test { public static void main(String[] args) { Outer.Inner in = new Outer().new Inner(); in.setName("内部"); in.show(); Outer.Inner.test(); System.out.println("------------"); Outer.Inner in1 = new Outer("爱听课").new Inner(); in1.show(); } }
1、成员内部类中是否可以直接访问外部类的静态成员?
可以,外部类的静态成员只有一份可以被共享访问。
2、成员内部类的实例方法中是否可以直接访问外部类的实例成员?
可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成
成员内部类-面试题
请观察如下代码,写出合适的代码对应其注释要求输出的结果。
class People{
private int heartbeat = 150;
public class Heart{
private int heartbeat = 110;
public void show(){
int heartbeat = 78;
System.out.println(??); // 78
System.out.println(??); // 110
System.out.println(??); // 150
}
}
}注意:在成员内部类中访问所在外部类对象 ,格式:外部类名.this。
public class Test2 { public static void main(String[] args) { People.Heart heart = new People().new Heart(); heart.show(); } } class People{ private int heartbeat = 150; /** 成员内部类 */ public class Heart{ private int heartbeat = 110; public void show(){ int heartbeat = 78; System.out.println(heartbeat); // 78 System.out.println(this.heartbeat); // 110 System.out.println(People.this.heartbeat); // 150 } } }
局部内部类:
局部内部类放在方法、代码块、构造器等执行体中。局部内部类的类文件名为: 外部类$N内部类.class。/** 目标:了解局部内部类的语法 */ public class Test { static { class Dog{ } abstract class Animal{ } interface SportManInter{ } } public static void main(String[] args) { class Cat{ private String name; public static int onLineNumber = 100; public String getName() { return name; } public void setName(String name) { this.name = name; } } interface SportManInter{ } Cat c = new Cat(); c.setName("叮当猫~"); System.out.println(c.getName()); } }
匿名内部类:
本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等。作用 :方便创建子类对象,最终目的为了简化代码编写。new 类|抽象类名|或者接口名() {
重写方法;
};Animal a = new Animal() {
public void run() {
}
};
a. run();总结:
匿名内部类是一个没有名字的内部类。匿名内部类写出来就会产生一个匿名内部类的对象。匿名内部类的对象类型相当于是当前new的那个的类型的子类类型。/** 目标:学习匿名内部类的形式和特点。 */ public class Test { public static void main(String[] args) { Animal a = new Animal(){ @Override public void run() { System.out.println("老虎跑的块~~~"); } }; a.run(); } } //class Tiger extends Animal{ // @Override // public void run() { // System.out.println("老虎跑的块~~~"); // } //} abstract class Animal{ public abstract void run(); }
匿名类常见使用形式:
某个学校需要让老师,学生,运动员一起参加游泳比赛/*游泳接口*/
public interface Swimming {
void swim();
}/* 测试类*/
public class JumppingDemo {
public static void main(String[] args) {
//需求:goSwimming方法
}
// 定义一个方法让所有角色进来一起比赛
public static void goSwimming(Swimming swimming) {
swimming.swim();
}
}匿名内部类可以作为方法的实际参数进行传输。
/** 目标:掌握匿名内部类的使用形式(语法) */ public class Test2 { public static void main(String[] args) { Swimming s = new Swimming() { @Override public void swim() { System.out.println("学生快乐的自由泳🏊"); } }; go(s); System.out.println("--------------"); Swimming s1 = new Swimming() { @Override public void swim() { System.out.println("老师泳🏊的贼快~~~~~"); } }; go(s1); System.out.println("--------------"); go(new Swimming() { @Override public void swim() { System.out.println("运动员🏊的贼快啊~~~~~"); } }); } /** 学生 老师 运动员可以一起参加游泳比赛 */ public static void go(Swimming s){ System.out.println("开始。。。"); s.swim(); System.out.println("结束。。。"); } } interface Swimming{ void swim(); }
匿名内部类真实使用场景演示
给按钮绑定点击事件
// 为按钮绑定点击事件监听器。
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("登录一下~~");
}
});
// btn.addActionListener(e -> System.out.println("登录一下~~"));import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** 目标:通过GUI编程 理解匿名内部类的真实使用场景 */ public class Test3 { public static void main(String[] args) { // 1、创建窗口 JFrame win = new JFrame("登录界面"); JPanel panel = new JPanel(); win.add(panel); // 2、创建一个按钮对象 JButton btn = new JButton("登录"); // 注意:讲解匿名内部类的使用 btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(win, "点我一下,说明爱我!"); } }); // btn.addActionListener( e -> JOptionPane.showMessageDialog(win, "别说话,吻我!!") ); // 3、把按钮对象添加到桌布上展示 panel.add(btn); // 4、展示窗口 win.setSize(400, 300); win.setLocationRelativeTo(null); win.setVisible(true); } }
3、常用API - Object
①Object类的方法是一切子类对象都可以直接使用的,所以我们要学习Object类的方法。②一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类。
Object类的常用方法:
方法名
说明
public String toString()
默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址
public boolean equals(Object o)
默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false
Object的toString方法:
父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
方法名 说明 public String toString()
默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址
Object的equals方法:
父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则。
方法名 说明 public boolean equals(Object o) 默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false /** 目标:掌握Object类中toString方法的使用。 */ public class Test1 { public static void main(String[] args) { Student s = new Student("周雄", '男', 19); // String rs = s.toString(); // System.out.println(rs); // System.out.println(s.toString()); // 直接输出对象变量,默认可以省略toString调用不写的 System.out.println(s); } }
import java.util.Objects; /** 目标:掌握Object类中equals方法的使用。 */ public class Test2 { public static void main(String[] args) { Student s1 = new Student("周雄", '男', 19); Student s2 = new Student("周雄", '男', 19); // equals默认是比较2个对象的地址是否相同,子类重写后会调用子类重写的来比较内容是否相同。 System.out.println(s1.equals(s2)); System.out.println(s1 == s2); System.out.println(Objects.equals(s1, s2)); } }
import java.util.Objects; public class Student { //extends Object{ private String name; private char sex; private int age; public Student() { } public Student(String name, char sex, int age) { this.name = name; this.sex = sex; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } /** 定制相等规则。 两个对象的内容一样就认为是相等的 s1.equals(s2) 比较者:s1 == this 被比较者: s2 ==> o */ @Override public boolean equals(Object o) { // 1、判断是否是同一个对象比较,如果是返回true。 if (this == o) return true; // 2、如果o是null返回false 如果o不是学生类型返回false ...Student != ..Pig if (o == null || this.getClass() != o.getClass()) return false; // 3、说明o一定是学生类型而且不为null Student student = (Student) o; return sex == student.sex && age == student.age && Objects.equals(name, student.name); } /** 自己重写equals,自己定制相等规则。 两个对象的内容一样就认为是相等的 s1.equals(s2) 比较者:s1 == this 被比较者: s2 ==> o */ /* @Override public boolean equals(Object o){ // 1、判断o是不是学生类型 if(o instanceof Student){ Student s2 = (Student) o; // 2、判断2个对象的内容是否一样。 // if(this.name.equals(s2.name) && // this.age == s2.age && this.sex == s2.sex){ // return true; // }else { // return false; // } return this.name.equals(s2.name) && this.age == s2.age && this.sex == s2.sex ; }else { // 学生只能和学生比较,否则结果一定是false return false; } }*/ @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex=" + sex + ", age=" + age + '}'; } }
3.1 常用API - Objects
Objects 是一个工具类 ,提供了一些方法去完成一些功能。官方在进行字符串比较时,没有用字符串对象的的 equals 方法,而是选择了 Objects 的 equals 方法来比较。@Override
public boolean equals(Object o) {
// 1、判断是否是同一个对象比较,如果是返回true。
if (this == o) return true;
// 2、如果o是null返回false 如果o不是学生类型返回false ...Student != ..Pig
if (o == null || this.getClass() != o.getClass()) return false;
// 3、说明o一定是学生类型而且不为null
Student student = (Student) o;
return sex == student.sex && age == student.age && Objects.equals(name, student.name);
}使用Objects的equals方法在进行对象的比较会更安全。
import java.util.Objects; /** 目标:掌握objects类的常用方法:equals */ public class Test { public static void main(String[] args) { String s1 = null; String s2 = new String("itheima"); // System.out.println(s1.equals(s2)); // 留下了隐患,可能出现空指针异常。 System.out.println(Objects.equals(s1, s2)); // 更安全,结果也是对的! /** Objects: public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); } */ System.out.println(Objects.isNull(s1)); // true System.out.println(s1 == null); // true System.out.println(Objects.isNull(s2)); // false System.out.println(s2 == null); // false } }
Objects的常见方法:
方法名
说明
public static boolean equals(Object a, Object b)
比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常。再进行equals比较
public static boolean isNull(Object obj)
判断变量是否为null ,为null返回true ,反之
3.2 常用API - StringBuilder
StringBuilder 是 一个可变的字符串类,我们可以把它看成是 一个对象容器。作用 :提高字符串的操作效率,如拼接、修改等。StringBuilder 构造器
名称
说明
public StringBuilder()
创建一个空白的可变的字符串对象,不包含任何内容
public StringBuilder(String str)
创建一个指定字符串内容的可变字符串对象
StringBuilder常用方法
方法名称
说明
public StringBuilder append(任意类型)
添加数据并返回StringBuilder对象本身
public StringBuilder reverse()
将对象的内容反转
public int length()
返回对象内容长度
public String toString()
通过toString()就可以实现把StringBuilder转换为String
/** 目标:学会使用StringBuilder操作字符串,最终还需要知道它性能好的原因 */ public class StringBuilderDemo1 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); // "" sb.append("a"); sb.append("b"); sb.append("c"); sb.append(1); sb.append(false); sb.append(3.3); sb.append("abc"); System.out.println(sb); StringBuilder sb1 = new StringBuilder(); // 支持链式编程 sb1.append("a").append("b").append("c").append("我爱你中国"); System.out.println(sb1); // 反转 sb1.reverse().append("110"); System.out.println(sb1); System.out.println(sb1.length()); // 注意:StringBuilder只是拼接字符串的手段:效率好。 // 最终的目的还是要恢复成String类型。 StringBuilder sb2 = new StringBuilder(); sb2.append("123").append("456"); // 恢复成String类型 String rs = sb2.toString(); check(rs); } public static void check(String data){ System.out.println(data); } }
案例:
打印整型数组内容
需求:
设计一个方法用于输出任意整型数组的内容,要求输出成如下格式:
“该数组内容为:[11, 22, 33, 44, 55]”
分析:
1、定义一个方法,要求该方法能够接收数组,并输出数组内容。 ---> 需要参数吗?需要返回值类型申明吗?
2、定义一个静态初始化的数组,调用该方法,并传入该数组。
public class StringBuilderTest2 { public static void main(String[] args) { int[] arr1 = null; System.out.println(toString(arr1)); int[] arr2 = {10, 88, 99}; System.out.println(toString(arr2)); int[] arr3 = {}; System.out.println(toString(arr3)); } /** 1、定义方法接收任意整型数组,返回数组内容格式 */ public static String toString(int[] arr){ if(arr != null){ // 2、开始拼接内容。 StringBuilder sb = new StringBuilder("["); for (int i = 0; i < arr.length; i++) { sb.append(arr[i] ).append(i == arr.length - 1 ? "" : ", "); } sb.append("]"); return sb.toString(); }else { return null; } } }
3.3 常用API - Math
① 包含执行基本数字运算的方法, Math 类没有提供公开的构造器。②如何使用类中的成员呢? 看类的成员是否都是静态的,如果是,通过类名就可以直接调用Math 类的常用方法
方法名
说明
public static int abs(int a)
获取参数绝对值
public static double ceil(double a)
向上取整
public static double floor(double a)
向下取整
public static int round(float a)
四舍五入
public static int max(int a,int b)
获取两个int值中的较大值
public static double pow(double a,double b)
返回a的b次幂的值
public static double random()
返回值为double的随机值,范围[0.0,1.0)
/** 目标:Math类的使用。 Math用于做数学运算。 Math类中的方法全部是静态方法,直接用类名调用即可。 方法: 方法名 说明 public static int abs(int a) 获取参数a的绝对值: public static double ceil(double a) 向上取整 public static double floor(double a) 向下取整 public static double pow(double a, double b) 获取a的b次幂 public static long round(double a) 四舍五入取整 小结: 记住。 */ public class MathDemo { public static void main(String[] args) { // 1.取绝对值:返回正数 System.out.println(Math.abs(10)); // 10 System.out.println(Math.abs(-10.3)); // 10.3 // 2.向上取整: 5 System.out.println(Math.ceil(4.00000001)); // 5.0 System.out.println(Math.ceil(4.0)); // 4.0 // 3.向下取整:4 System.out.println(Math.floor(4.99999999)); // 4.0 System.out.println(Math.floor(4.0)); // 4.0 // 4.求指数次方 System.out.println(Math.pow(2 , 3)); // 2^3 = 8.0 // 5.四舍五入 10 System.out.println(Math.round(4.49999)); // 4 System.out.println(Math.round(4.500001)); // 5 System.out.println(Math.random()); // 0.0 - 1.0 (包前不包后) // 拓展: 3 - 9 之间的随机数 (0 - 6) + 3 // [0 - 6] + 3 int data = (int)(Math.random() * 7) + 3; System.out.println(data); } }
3.4 常用API - System
System也是一个工具类,代表了当前系统,提供了一些与系统相关的方法。
System 类的常用方法
方法名
说明
public static void exit(int status)
终止当前运行的 Java 虚拟机,非零表示异常终止
public static long currentTimeMillis()
返回当前系统的时间毫秒值形式
public static void arraycopy(数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数)
数组拷贝
import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.Arrays; /** 目标:System系统类的使用。 System代表当前系统。(虚拟机系统) 静态方法: 1.public static void exit(int status):终止JVM虚拟机,非0是异常终止。 2.public static long currentTimeMillis():获取当前系统此刻时间毫秒值。(重点) 3.可以做数组的拷贝。 arraycopy(Object var0, int var1, Object var2, int var3, int var4); * 参数一:原数组 * 参数二:从原数组的哪个位置开始赋值。 * 参数三:目标数组 * 参数四:赋值到目标数组的哪个位置 * 参数五:赋值几个。 */ public class SystemDemo { public static void main(String[] args) { System.out.println("程序开始。。。"); // System.exit(0); // JVM终止! // 2、计算机认为时间有起源:返回1970-1-1 00:00:00 走到此刻的总的毫秒值:时间毫秒值。 long time = System.currentTimeMillis(); System.out.println(time); long startTime = System.currentTimeMillis(); // 进行时间的计算:性能分析 for (int i = 0; i < 100000; i++) { System.out.println("输出:" + i); } long endTime = System.currentTimeMillis(); System.out.println((endTime - startTime)/1000.0 + "s"); // 3、做数组拷贝(了解) /** arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 参数一:被拷贝的数组 参数二:从哪个索引位置开始拷贝 参数三:复制的目标数组 参数四:粘贴位置 参数五:拷贝元素的个数 */ int[] arr1 = {10, 20, 30, 40, 50, 60, 70}; int[] arr2 = new int[6]; // [0, 0, 0, 0, 0, 0] ==> [0, 0, 40, 50, 60, 0] System.arraycopy(arr1, 3, arr2, 2, 3); System.out.println(Arrays.toString(arr2)); System.out.println("-------------------"); double i = 10.0; double j = 3.0; // // System.out.println(k1); System.out.println("程序结束。。。。"); } }
3.5 常用API - BigDecimal
用于解决浮点型运算精度失真的问题
使用步骤
创建对象 BigDecimal 封装浮点型数据 (最好的方式 是调用方法 )
public static BigDecimal valueOf ( double val) : 包装浮点数成为 BigDecimal 对象。BigDecima 常用方法
方法名
说明
public BigDecimal add(BigDecimal b)
加法
public BigDecimal subtract(BigDecimal b)
减法
public BigDecimal multiply(BigDecimal b)
乘法
public BigDecimal divide(BigDecimal b)
除法
public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式)
除法
import java.math.BigDecimal; import java.math.RoundingMode; import java.text.NumberFormat; /** 目标:BigDecimal大数据类。 引入: 浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。 BigDecimal可以解决浮点型运算数据失真的问题。 BigDicimal类: 包:java.math. 创建对象的方式(最好的方式:) public static BigDecimal valueOf(double val) :包装浮点数成为大数据对象。 方法声明 public BigDecimal add(BigDecimal value) 加法运算 public BigDecimal subtract(BigDecimal value) 减法运算 public BigDecimal multiply(BigDecimal value) 乘法运算 public BigDecimal divide(BigDecimal value) 除法运算 public double doubleValue(): 把BigDecimal转换成double类型。 */ public class BigDecimalDemo { public static void main(String[] args) { // 浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。 System.out.println(0.09 + 0.01); System.out.println(1.0 - 0.32); System.out.println(1.015 * 100); System.out.println(1.301 / 100); System.out.println("-------------------------"); double a = 0.1; double b = 0.2; double c = a + b; System.out.println(c); System.out.println("--------------------------"); // 包装浮点型数据成为大数据对象 BigDeciaml BigDecimal a1 = BigDecimal.valueOf(a); BigDecimal b1 = BigDecimal.valueOf(b); BigDecimal c1 = a1.add(b1); // BigDecimal c1 = a1.subtract(b1); // BigDecimal c1 = a1.multiply(b1); // BigDecimal c1 = a1.divide(b1); System.out.println(c1); // 目的:double double rs = c1.doubleValue(); System.out.println(rs); // 注意事项:BigDecimal是一定要精度运算的 BigDecimal a11 = BigDecimal.valueOf(10.0); BigDecimal b11 = BigDecimal.valueOf(3.0); /** 参数一:除数 参数二:保留小数位数 参数三:舍入模式 */ BigDecimal c11 = a11.divide(b11, 2, RoundingMode.HALF_UP); // 3.3333333333 System.out.println(c11); System.out.println("-------------------"); } }