一:前言:
最近趁着闲暇时间入门了Java,别说,学过其他语言是真滴快,一路二倍速加速,但是到了多态这个地方,发现逻辑啥的还是挺混乱的,于是乎。。。。。这篇文章就出现了!!!但是我不建议学语言记太多笔记,毕竟~~~无招胜有招~
什么是多态?
1.1多态概述
同一个对象,在不同时刻表现出来的不同形态
举例:猫
我们可以说猫是猫:猫cat = new猫();
我们也可以说猫是动物:动物animal = new猫();这里猫在不同的时刻表现出来了不同的形态,这就是多态
多态的前提和体现:
有继承/实现关系有方法重写
有父类引用指向子类对象
二:多态的优缺点:
一共有四个类:
Animal
AnimalDemo
AnimalOperator
Cat
package duotai;
//一个动物的大类
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
package duotai;
//猫类 并且重写方法
public class Cat extends Animal {
@Override
public void eat(){
System.out.println("猫吃骨头");
}
public void lookdoor(){
System.out.println("猫看门");
}
}
package duotai; //动物操作类 public class AnimalOperator { public void userAnimal(Cat c){ //相当于 Cat c = new Cat() c.eat(); } }
package duotai;
//测试类
public class AnimalDemo {
public static void main(String[] args) {
//创建动物操作类的对象,调用方法
AnimalOperator ao = new AnimalOperator();
Cat c = new Cat();
ao.userAnimal(c); //把猫类型传给了ao
}
}
但是每次这样AnimalOperator都要去添加一个方法去调用,很麻烦,于是
package duotai;
//动物操作类
public class AnimalOperator {
public void userAnimal(Animal a){
//相当于Animal a = new Cat(); 编译看左边,有eat方法,运行看右边,cat里面重写了cat方法所以输出重新后的方法
//如果有Dog类 那么下面不用加方法,直接相当于Animal a = new Dog(); 但是必须得重写过方法
a.eat();
a.lookdoor(); //报错~~~多态的形式不能访问具体的子类所特有的功能
}
}
这样就简化了编写,不用写多的方法,得出 多态 提高了程序的扩展性,具体的体现是:在定义方法的时候使用父类型作为参数,在将来使用的时候是使用具体的子类型
缺点是:多态的形式不能访问具体的子类所特有的功能
其中被注释的 c.playGame()是无法调用的,于是我们可以强制转换c为一个子类的对象
抽象的方法没有方法体。需要注意的是在抽象类中既可以有抽象方法,也可以有普通方法,注意抽象方法是没有方法体的(也就是方法后面是没有大括号的)。凡是继承这个抽象类的实体子类,都必须要实现这个抽象方法。
我们总结一下抽象类的特点:
(1)抽象类不能被实例化
(2)构造方法 和 static 方法不能是抽象的
(3)父类的抽象方法往往在子类中实现
(4)抽象类可以具有指向子类对象的对象引用
三:接口的特点
接口用关键字interface修饰
public interface接口名丹类实现接口用implements表示
public class 类名 implements 接口 名
接口不能实例化
接口如何实例化呢?
参照多态的方式,通过实现类对象实例化,这叫接口多态。多态的形式:具体类多态,抽象类多态,接口多态。
多态的前提:
有继承或者实现关系;有方法重写;
有父(类/接口)引用指向(子/实现)类对象接口的实现类
要么重写接口中的所有抽象方法要么是抽象类
例子:
思路:
定义接口(Jumpping)
成员方法:跳高();定义抽象动物类(Animal)
成员变量:姓名,年龄;构造方法:无参,带参;成员方法: get/set方法,吃饭(;③定义具体猫类(Cat),继承动物类,实现跳高接口
构造方法:无参,带参;成员方法:重写吃饭(){.….},重写跳高方法({.….}④定义狗类(Dog),继承动物类,实现跳高接口
构造方法:无参,带参;成员方法:重写吃饭({….},重写跳高方法({…]
package itheima_01;
//接口
public interface Jumpping {
public abstract void jump();
}
package itheima_01;
//动物类
public abstract class Animal {
private String name;
private int age;
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 Animal(String name, int age) {
this.name = name;
this.age = age;
}
public Animal() {
}
public abstract void eat();
}
package itheima_01;
//猫类
public class Cat extends Animal implements Jumpping{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public Cat(String name, int age) {
super(name, age);
}
public Cat() {
}
@Override
public void jump() {
System.out.println("调高");
}
}
package itheima_01;
public class AnimalDemo {
public static void main(String[] args) {
//创建对象,调用方法
Jumpping j = new Cat();
j.jump();
Animal a = new Cat();
a.setAge(5);
a.setName("加菲");
System.out.println(a.getAge()+a.getName());
a.eat();
//报错
//a.jump 故接口只能调接口里的方法 抽象类只能调抽象类里 的方法
//带参构造
a = new Cat("加菲",5);
System.out.println(a.getAge()+a.getName());
a.eat();
//cat继承了动物类也实现了接口,故更多时候用具体的类
Cat c = new Cat();
c.setAge(5);
c.setName("加菲");
System.out.println(c.getAge()+c.getName());
//都可以调用
c.eat();
c.jump();
}
}
1.抽象类和接口的区别
成员区别:
抽象类:
变量,常量;有构造方法;有抽象方法,也有非抽象方法
接口:
常量;抽象方法
关系区别:
类与类
继承,单继承
类与接口
实现,可以单实现,也可以多实现
接口与接口
继承,单继承,多继承
设计理念区别:
抽象类
对类抽象,包括属性、行为
接口
对行为抽象,主要是行为
重点来啦~~~:抽象类是对事物的抽象,接口是对行为的抽象
如下:
package itheima02;
//人大类
public abstract class Person {
private String name;
private int age;
public abstract void eat();
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
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;
}
}
package itheima02;
//说英语的接口
public interface SpeakEnglish {
public abstract void speak();
}
package itheima02;
//运动员类
public abstract class Player extends Person{
public abstract void study();
public Player(String name, int age) {
super(name, age);
}
public Player() {
}
}
package itheima02;
public class PingPongPlayer extends Player implements SpeakEnglish{
public PingPongPlayer() {
}
public PingPongPlayer(String name,int age){
super(name,age);
}
@Override
public void study() {
System.out.println("我要学乒乓球");
}
@Override
public void eat() {
System.out.println("我要吃粥");
}
@Override
public void speak() {
System.out.println("我要学英语");
}
}
package itheima02;
//测试
public class PersonDemo {
public static void main(String[] args) {
PingPongPlayer ppp = new PingPongPlayer();
ppp.setName("ooo");
ppp.setAge(18);
System.out.println(ppp.getAge()+ppp.getName());
ppp.eat();
ppp.speak();
ppp.study();
BasketballPlayer bp = new BasketballPlayer();
bp.setAge(10);
bp.setName("啊");
System.out.println(bp.getAge()+bp.getName());
bp.eat();
bp.study();
}
}
嫌麻烦就差不多得了~~~~~~~~~~~~~~
2.接口名作为形参和返回值
以接口作为形参,由于不能直接调用,需要创建一个具体类去重写方法在new一个新对象调用,如果一个方法的形参是接口名,那么它其实要的是该接口的实现类对象
作为返回值时
以多态的形式创建了接口的对象
3.内部类
按照内部类在类中定义的位置不同,可以分为如下两种形式,其实也就是不想让外部能访问到内部的内容
在类的成员位置:成员内部类
在类的局部位置:局部内部类
成员内部类:
即创建外部类的对象,调用method方法就可以调用内部类的show方法了
局部内部类:
外界无法直接访问,是要通过外部类的对象 调用method方法来间接访问
匿名内部类,属于局部内部类的一种
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
本质:是一个继承了该类或者实现了该接口的子类匿名对象
调用 method方法,可以访问这个内部类,其中 Inter 是一个接口
对象调用show方法,即可输出内容,但是呢,这样多次调用会很麻烦
于是:既然这个整体是一个对象,那么应该有返回值类型,因为new inter ,这个整体看成是一个Inter的实现类对象,按照多态的形式,赋值给Inter这个接口
这样于是就可以多次调用啦~~~~
那么匿名内部类在实际开发中怎么应用呢?
例如我写一个调高的接口,
demo中 因为形参是接口,所有每次都需要实现类,这样会麻烦,于是使用匿名内部类,因为匿名内部类的本质就是一个对象,并且是实现该接口的对象
这样就不用多写两个类并且new对象了~~~~~
三:System类和Object的个例
重点学习toString和equals方法
下面有一个例子:
取的是对象的地址,查看方法对应源代码,复制到 下面
可以看到 println(s)传递s到了 object x 之后Object x 传递到 Object obj ,,if判断中 obj不会是null,于是调用toString方法
建议所有子类覆盖此方法~~~于是 重写
equals方法:
那么如何单独的比较内容呢?即姓名年龄,
即重写equals方法
解析这段代码:
this — s1
o — s2
第一个if 比较地址,相同返回true
第二个if: 如果参数o为null 返回false || 判断两个对象是否来自同一个类,不同返回false
然后进行向下转型
第三个if 比较年龄
第四个if 比较姓名 其中 name 是String类型的,所以用equals比较名字是否相等
总结:
四:拆箱,装箱
我吐了,这个代码插件 不咋地呀
写的好好吖 膜拜大佬
不是啦~