多态
调用多态的方法如下,同一个行为表现出不同的行为特征
多态的常见形式
父类类型 对象名称 = new 子类构造器
接口 对象名称 = new 实现类构造器
使用方法1:
public class Animal{
public void run(){
//输入内容
}
}
//狗继承方法重新
public class Dog extends Animal{
public String name="变量名称1"
@Override
public void run(){
//重新内容
}
}
//乌龟继承方法重新
public class Tortoise extends Animal{
public String name="变量名称2"
@Override
public void run(){
//重新内容
}
}
public class Test {
public static void main(String[] args) {
//目标:先认识多态形式
//父类:对象名称= new 子类构造器();
Animal a = new Dog();
a.run();
a.name//变量名称1
Animal a1=new Tortoise();
a1.run();
a1.name//变量名称2
}
}
使用方法2
public class Test {
public static void main(String[] args){
Animal d=new Dog();
go(d);
d.Animal里面的方法;//可以
d.Dog里面的方法;//报错
}
public static void go(Animal a){
System.out.println("第一步")
a.run(); //第二步
System.out.println("第三步")
}
}
多态中成员访问特点
- 方法调用:编译看左边,运行看右边
- 变量调用:编译看左边,运行也看左边。(多态侧重行为多态)
多态前提
有继承/实现关系;有父类引用指向子类对象;有方法重写
多态的优势
- 多态形式下,右边对象可以实现解耦合,便于扩展和维护
Animal a = new Dog();
a.run(); // 后续业务行为随对象而变,后续代码无需修改
- 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。
多态的劣势
- 多态下不能使用子类的独有功能
多态的类型转换
自动类型转换(子到父):之而立对象赋值给父类类型的变量指向
强制类型转换(父到子):
- 此时必须进行强制类型转换:子类 对象变量=(子类)父类类型的变量
- 作用:可以解决多态下的劣势,可以实现调用子类独有 的功能
- 注意:如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException
Animal t = new Tortoise(); Dog d=(Dog)t; // 出现异常 ClassCastException
java建议强制装换前使用instanceof判断当前对象的真实类型,再进行强制转换
变量名 instanceof 真实类型
判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之返回false
多态的综合案例
有参数构造器的创建
//创建一个接口
public interface USB {
//接入
void connect();
//拔出
void unconnect();
}
//创建一个鼠标实现接口
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 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+"写下了评论,评论了666666");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//创建一个电脑
public class Computer {
/**
提供一个安装入口:用一个行为代表
*/
public void install(USB usb){
usb.connect();
//独有功能 判断真实类型并强转
if(usb instanceof Mouse){
Mouse m = (Mouse)usb;
m.click();
}else if(usb instanceof KeyBoard){
KeyBoard m=(KeyBoard)usb;
m.keyDown();
}
usb.unconnect();
}
}
//创建一个电脑
public class Computer {
/**
提供一个安装入口:用一个行为代表
*/
public void install(USB usb){
usb.connect();
//独有功能
if(usb instanceof Mouse){
Mouse m = (Mouse)usb;
m.click();
}else if(usb instanceof KeyBoard){
KeyBoard m=(KeyBoard)usb;
m.keyDown();
}
usb.unconnect();
}
}
//创建一个方法接入鼠标和键盘
/**
目标:USB设备模拟
1.定义USB接口:接入 拔出
2.定义一个USB实现类:鼠标、键盘
3.创建一个电脑对象,再创建一个鼠标对象,模拟运行
*/
public class Test {
public static void main(String[] args) {
//创建定安路对象
Computer c= new Computer();
//创建USB设备对象
USB usb =new Mouse("罗杰鼠标");
c.install(usb);
}
}
内部类
public class People{
//内部类
public class Heart{
}
}
//运行方式
//外部类名.内部类名 对象 = new 外部类名.内部类名
People.Heart p=new People.Heart
- 当一个事物的内部,还有一个部分需要一个完整的解构进行描述,而这个内部的完整解构又只为外部事物提供服务,那么整个内部的完整结构可以使用内部类来设计。
- 内部类通常可以方便访问外部类的成员,包括私有成员。
- 内部类提供了更好的封装性,内部类本身就可以使用private protected等修饰,封装性可以做更多控制。
静态类的使用场景、特点、访问总结
- 如果一个类中包含了一个完整的成分,如汽车类中的发动机类
- 特点、使用与普通类是一样的,类有的成分它都有,只是位置在别人里面而已
- 可以直接访问外部类的静态成员,不能直接访问外部类的实例成员。
- 注意:开发实际上用的还是比较少的。
成员内部类创建对象的格式
格式:外部类名.内部类名 对象名 = new 外部内构造器.new 内部类构造器
范例:Outer.Inner in = new Outer().new Inner();
匿名内部类
- 本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等。
- 作用:方便创建子类对象,最终目的为了简化代码编写
格式: new 类 | 抽象类名 | 或者接口名(){ 重写方法 };
特点:
- 匿名内部类是一个没有名字的内部类。
- 匿名内部类写出来就会产生一个匿名内部类的对象。
- 匿名内部类的对象类型相当于是当前new的那个类型的子类类型。
案例
//为按钮绑定点击事件监听器
btn.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
System.out.println("登录一下~~")
}
})
//btn.addActionListener(e->System.out.println("登录一下~~"))
//模拟点击登录
public class btn {
public static void main(String[] args) {
JFrame win = new JFrame();
JPanel Panel= new JPanel();
win.add(Panel);
JButton btn=new JButton("登录");
Panel.add(btn);
win.setLocationRelativeTo(null);
win.setSize(300,200);
win.setVisible(true);
btn.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win,"弹出提示框");
}
});
}
}
常用API
Object
toString方法
输出地址 // @Override...重写方法
equals方法:
比较地址返回true或false s1.equals(s2) 默认比较地址是否相同 //@Override 重写
使用方法二:Objects.equals(s1,s2)
isNull方法
isNull(s1) 判断s1是否为null
StringBuilder 增加拼接效率
StringBuilder是一个可变字符串类,我们可以吧它看成一个对象容器
作用:提高字符串的操作效率,如拼接、修改等。
方法名称 | 说明 |
public StringBuilder append(任何类型) | 添加数据并返回StringBuilder对象本身 |
public StringBuilder reverse() | 将对象的内容反转 |
public int length() | 返回对象内容长度 |
public String toString() | 通过toString()j就可以实现吧StringBuilder转换为String |
使用方法
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) |
System
方法名 | 说明 |
public static void exit(int status) | 终止当前运行的java虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前系统的时间毫秒值形式 从1970-1-1 00:00:00 算起 |
public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数) | 数组拷贝 |
BigDecimal 用于解决浮点型运算精准度失真的问题
1.public static BigDecimal valueOf(double val) //将浮点类型包装成BigDecimal对象
方法名 | 说明 |
public BigDecimal add(BigDecimal b) | 加法 |
public BigDecimal subtract(BigDecimal b) | 减法 |
public BigDecimal multiply(BigDecimal b) | 乘法 |
public BigDecimal divide(BigDecimal b) | 除法 |
public BigDecimal divide(另一个BigDecimal 对象,精确几位,舍入模式) | 除法 |
推荐使用BigDecimal val =BigDecimal.valueOf(数字)