重温JavaSE10

多态(重点)

多态的定义:

多态就是多种状态:同一个行为,不同的子类表现出来不同的形态。

多态指的就是同一个方法调用,然后由于对象不同会产生不同的行为。

多态的好处:

为了提高代码的扩展性,符合开闭原则。

(开闭原则:指的就是扩展是开放的,修改是关闭的。)

多态的要素(使用的前提条件):
  1. 继承: Cat extends Animal Pig extends Animal Dog extends Animal
  2. 重写:子类对父类的方法shout()重写
  3. 父类引用指向子类对象(父类做参数/返回值类型) (声明父类,new子类) 向上转型
父类引用指向子类对象的说明:
//子类 对象名 = new 子类();
//对象可以调用重写父类的方法,也可以调用子类特有的方法(不支持多态)
//父类 对象名 = new 子类();
//只能调用重写父类的方法(相当是个父类对象),不能调用子类特有的方法(可向下转型进行修改,支持多态)
什么是动态绑定:

程序在编写时,父类做参数
但是程序在运行时,会根据传入的实际子类对象动态调用对应的方法。

什么题用多态:

肯定是两条线;两条线一定有交点;多态体现在第二条业务线上

(例如小女孩跟猫、狗、蛇玩)(没有第二条业务线就只定义继承即可)

看下面干货分享

public class Pet {
    public void eat(){
        System.out.println("宠物在吃东西...");
    }
}
public class Cat extends Pet{//继承
    @Override
    public void eat() {//重写
        System.out.println("猫在吃鱼!");
    }
}
public class Dog extends Pet{//继承
    @Override
    public void eat() {//重写
        System.out.println("狗吃骨头!");
    }
}
/**
 * 多态的第二条业务线
 */
public class Child {
//    public void playPat(Cat cat){//说明:小朋友跟小猫玩
//        cat.eat();
//    }
//    public void playPat(Dog dog){//说明:小朋友跟小狗玩
//        dog.eat();
//    }
    //问题在动物多的时候要写好多方法
    public void playPat(Pet pet){//父类做对象,程序会根据具体的子类对象,动态的调用子类的方法
        System.out.print("小女孩看着");
        pet.eat();
    }
    public void playPat2(Pet pet){
        System.out.print("小女孩又来看");
        if (pet instanceof Cat){//判断对象是不是该类型
            ((Cat)pet).eat();//向下转型,强转
        }else if (pet instanceof Dog){
            ((Dog)pet).eat();//向下转型,强转
        }
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Child child = new Child();
        Pet cat = new Cat();//向上转型
        child.playPat(cat);
        child.playPat(new Dog());//直接传一个无参构造的狗对象
        Cat c =(Cat)cat;//向下转型
        c.eat();
        child.playPat2(cat);
        Pet dog = new Dog();
        child.playPat2(dog);
    }
    /*
面向对象第三个特点:多态
封装(数据的安全、整合)->继承(代码的重用)->多态(代码的扩展)->(反射:把代码扩展到极致)
    1.多态发生的场合:(不是所有题都适合用多态的)
        1)题目中有两个业务线,第一条是继承线(1父,>=2子)
          第二条业务线:一定有另外一个群体,该群体中的某一行为跟继承线中的多个子类是依赖关系
          ##(例如小女孩跟猫、狗、蛇玩)(没有第二条业务线就只定义继承即可)
    2.什么是多态?(多态只关注行为(方法),不关注属性)
        =====实现多态的前提条件(继承+重写方法)
        1)不同的子类对象,作为参数在参与同一行为时,有不同的表现形式就叫多态。
        2)动态绑定:程序在编写时,父类做参数
                   但是程序在运行时,会根据传入的实际子类对象动态调用对应的方法。

    3.实现多态的前提条件:继承、方法的重写、父类引用指向子类对象。(声明父类,new子类)向上转型
    4.解释【父类引用指向子类对象】
        子类 对象名 = new 子类();
        对象可以调用重写父类的方法,也可以调用子类特有的方法(不支持多态)
        父类 对象名 = new 子类();
        只能调用重写父类的方法(相当是个父类对象),不能调用子类特有的方法(可向下转型进行修改,支持多态)
    5.多态的实现方法有两种:
        父类做参数
        父类做返回值
    6.Java中引用数据类型的类型转换
      子类<父类
      【向上转型】小转大:自动转换:声明父类,new子类
        Pet pet = new Cat();
        注意:向上转型后,创建的对象只能调用重写父类的方法(相当是个父类对象),不能调用子类特有的方法(可再向下转型进行修改)
      【向下转型】大转小,强自转或:声明子类,父类强转成子类
        Cat cat = (Cat) pat;
        注意:想要向下转型该对象曾经必须向上转型过,向下转型时类型要匹配,否则报ClassCastException错误
        【解决方案】instanceof判断类型避免异常
        if(i instanceof Dog){//判断i对象是不是狗类型的
            ((Dog)i).eat();
        }
      Java中基本数据类型的类型转换
      boolean不参加转换,(char,byte,short)<int<long<float<double
      小转大:自动转换  大转小:强制转换
     */
}

Java中引用数据类型的类型转换(重点)

子类<父类

向上转型(向父类转)

小转大:自动转换:声明父类,new子类
Pet pet = new Cat();
注意:向上转型后,创建的对象只能调用重写父类的方法(相当是个父类对象),不能调用子类特有的方法(可再向下转型进行修改)

向下转型(向子类转)

大转小:强自转或:声明子类,父类强转成子类
Cat cat = (Cat) pat;
注意:想要向下转型该对象曾经必须向上转型过,向下转型时类型要匹配,否则报ClassCastException错误
可通过instanceof判断类型避免异常

if(i instanceof Dog){//判断i对象是不是狗类型的
    ((Dog)i).eat();
}
Java中基本数据类型的类型转换

boolean不参加转换

(char,byte,short)<int<long<float<double

小转大:自动转换

大转小:强制转换

抽象类和抽象方法(重点)

**以后父类应全改成抽象类**

抽象类和抽象方法的作用:

目的是为子类提供一个通用的模板,子类可以在模板的基础上进行开发,先重写父类的抽象方法,然后可以扩展子类自己的内容。抽象类设计避免了子类设计的随意性,通过抽象类,子类的设计变得更加严格,进行某些程度上的限制。

抽象类考点:
  1. 抽象类不能创建对象
  2. 抽象类有构造器(只供子类调用,顶级父类还是Object)
  3. 非子类不能调用抽象父类的构造器
  4. 抽象类不能被final修饰,因为final修饰的类没有子类
抽象方法考点:
  1. 一个类中,只要有抽象方法,这个类一定是抽象类
  2. 抽象类中可以没有抽象方法
  3. 子类必须重写父类里的抽象方法,若没重写全部抽象方法,那么子类必须改为抽象类
package com.jr.curriculum.demo2;
public abstract class Demo2 {
    public void Demo2(){
        System.out.println("抽象类的构造方法");
    }
    public abstract void test();//抽象方法,必须被子类重写
    /*
【抽象类、抽象方法】
抽象类:在程序中父类对象没有创建的必要了,如何告诉开发者不再创建父类对象:
           public 【abstract】 class 类名
        说明:
            1.抽象类不能创建对象
            2.抽象类有构造器(只供子类调用,顶级父类还是Object)
            3.非子类不能调用抽象父类的构造器
抽象方法:在程序中父类要求子类重写方法,
            public 【abstract】 void test();
        说明:
            1.一个类中,只要有抽象方法,这个类一定是抽象类
            2.抽象类中可以没有抽象方法
            3.子类必须重写父类里的抽象方法,若没重写全部抽象方法,那么子类必须改为抽象类
     */
}
public abstract class Test1 extends Demo2{//没有重写父类的抽象方法,那么必须变成抽象类
}
public class Test2 extends Test1{
    @Override
    public void test() {//重写父类的抽象方法
        System.out.println("子类重写父类的抽象方法");
    }
}

final关键字(重点)

final修饰变量:

会变成常量

  1. 常量名应该全大写(规范)
  2. 常量应该声明同时赋值(规范)
  3. 常量存在常量池,相同信息不会重复存储
  4. final修饰的是基本类型,值不可修改。
  5. final修饰的是引用类型,地址不可修改,对象的属性值可改。
修饰方法:

不能被重写

修饰类:

不能被继承(不能有子类)

看下面干货分享

public class Demo3 /*extends String不能有子类*/{
    public static void main(String[] args) {
        final int A = 123;
//        A = 12;//不可再改值了
        final Demo3 demo3 = new Demo3();
//        demo3 = new Demo3();//不可再改地址了

    }
    final public void test(){//不能被子类重写
    }
    /*
【final关键字】:最终的
可修饰:属性、方法、类
    1.修饰变量:会变成常量
        1)常量名应该全大写(规范)
        2)常量应该声明同时赋值(规范)
        3)常量存在常量池,相同信息不会重复存储
        4)final修饰的是基本类型,值不可修改。
          final修饰的是引用类型,地址不可修改。
    2.修饰方法:不能被重写
    3.修饰类:不能被继承(不能有子类)
     */
}

接口(重点※)

接口的作用:

为了解决Java的继承单根性(单继承) 首先想到的是内部类,之后用接口解决

接口的定义:

具有共同行为的几组对象的集合叫接口
类的定义:具有相同属性和共同行为的一组对象的集合叫类

重点:抽象父类和接口的异同
接口的不同抽象类的不同
没有构造器有构造器,但不能调用。(默认带无参构造)
接口关键字:interface抽象类关键字:abstract class
一个类可以多实现接口一个类只能单继承父类
定义的变量都是全局静态常量可以定义常量和变量
共同点
都不能实例化对象
都可以实现多态, 接口可以声明 接口 new 实现类();
都有抽象方法和非抽象方法, (接口在1.8版本以后,且要default修饰,public default void(){内容},允许重写)
如果当前类没有实现(抽象类/接口)的所有抽象方法,那么这个类必须是抽象类。

下面干货分享

/**
 *抽象父类:因为父类没有创建对象的必要
 * 子类共有的行为和属性提取出来做抽象父类等子类实现
 */
public abstract class Door {
    private double hight;
    private double wide;
    public abstract void open();
    public abstract void close();
}
public class HouseDoor extends Door implements BellRings/*,可放多个接口*/{
    @Override
    public void rings() {//实现接口的方法
        System.out.println("门铃响了");
    }
    @Override
    public void open() {
        System.out.println("房门打开");
    }
    @Override
    public void close() {
        System.out.println("房门关闭");
    }
}
public interface BellRings {//门铃接口
    void rings();
}
public class Demo4 {
    public static void main(String[] args) {

    }
    /*
【接口】
1.作用:为了解决Java的继承单根性(单继承)       首先想到的是内部类,之后用接口解决
2.什么是接口:
    接口:具有共同行为的几组对象的集合叫接口
    类:具有相同属性和共同行为的一组对象的集合叫类
3.如何使用接口:
    定义接口:public interface 接口名{}
    实现接口:public class 类 interface 接口{}
    举例子:门  方法:开、关、指纹解锁、密码解锁     共性的放在父抽象类,特性的放在接口
               属性:高、宽、颜色

    接口直接可以多实现,类直接只能单继承
    【重点:抽象父类和接口的异同】
    1.接口不能创建对象 因为没有构造器
      抽象父类也不能创建对象 有构造器,但不能调用。
    2.接口关键字:interface
      抽象类关键字:abstract class
    3.一个类只能单继承父类
      一个类可以多实现接口
    4.接口也可以实现多态
      声明接口 new 实现类();
    5.抽象父类中可以有抽象方法和非抽象方法
      接口中可以有抽象方法和非抽象方法(1.8版本以后的,且要在方法前权限修饰符改为default,允许重写)
      public default void(){内容} //允许重写
      public static void(){内容} //不允许重写
     */
}

内部类(了解,能看懂源码即可)

概述:

一个类的内部又完整的嵌套了另一个类的结构,被嵌套的是内部类,嵌套其他类的叫外部类。

类的成员:

属性、方法、构造器、代码块、内部类

也是为了解决java 单根性。

局部内部类

位置:外部类的方法、代码块、构造器内

特点:

  1. 有类名
  2. 和正常类一样使用
  3. 只能用final修饰,相当于局部变量,作用域只在定义的方法、代码块、构造器里生效
  4. 在局部内部类的方法或代码块中可直接访问外部类的成员和方法(含私有)
  5. 外部类可直接实例化内部类对象,然后使用内部类的资源
  6. 其他外部类不能直接使用,可以通过外部类实例化内部类对象,然后使用内部类的资源
  7. 内部类和外部类重名则就近原则,内部类可使用外部类名.this.成员 访问
public class LocalInnerClass {
    public static void main(String[] args) {
        Test test = new Test();
        test.aaa();//外部类的方法,该方法在下面实例化了局部内部类并调用bbb方法,局部内部类中的bbb方法又实例化了内部类的内部类并调用方法才进行的输出。
    }
}
class Test {//外部类
    private int i = 100;//外部类的私有成员
    private void test(){
        System.out.println("我是外部类的私有方法,可以被内部类调用");
    }
    public void aaa(){//外部类的方法
        class Inner{//局部内部类,定义在外部类的方法或代码块里
            public void bbb(){
                System.out.println("我是内部类的方法,我调用内部类的内部类的方法");
                class Inner2{//内部类的内部类
                    public void ccc(){
                        System.out.println("我是内部类的内部类的方法,外部类i的值为:"+i);//在内部类的方法或代码块中可直接访问外部类私有的成员和方法
                        test();
                    }
                }
                Inner2 inner2 = new Inner2();//不这样写外部类无法访问内部类
                inner2.ccc();
            }
        }
        Inner inner = new Inner();
        inner.bbb();
    }
}
匿名内部类

位置:外部类的方法、代码块、构造器内

特点:

  1. 无类名(系统分配的名字不能直接看到,名字是类名$n)

  2. 本质还是一个类

  3. 同时还可以看做是一个对象(看下面特点6)

  4. 只能添加访问修饰符,相当于局部变量,作用域只在定义的方法、代码块、构造器里生效

  5. 为了继承父类或实现接口时不用特意写一个类,减少代码量

    (直接继承父类并实例化生成对象)(直接实现接口并实例化生成对象)<-可通过新对象接收

  6. 只用类里的方法,都不用新对象接收了,本身看成对象.方法即可

  7. 外部类可直接实例化内部类对象,然后使用内部类的资源

  8. 其他外部类不能直接使用,可以通过外部类实例化内部类对象,然后使用内部类的资源

  9. 内部类和外部类重名则就近原则,内部类可使用外部类名.this.成员 访问

声明方式:

父类或接口 名 new 父类或接口(参数列){

​ 类体

};

public class AnonymousInnerClass {//匿名内部类使用

    public static void main(String[] args) {
        Test01 test01 = new Test01();
        test01.aaa();//外部类的方法,方法里的匿名内部类实现了接口
    }
}
class Test01 {//外部类
    private int i = 100;//外部类的私有属性
    private void test(){
        System.out.println("我是外部类的私有方法,可以被内部类调用");
    }
    public void aaa(){//外部类的方法
        //基于接口的匿名内部类
        Inter inter = new Inter() {//直接实现接口并实例化生成对象,然后将对象赋给inter对象
            @Override
            public void inter() {//实现接口里的方法
                System.out.println("我实现了接口里的inter方法");
                test();
                System.out.println("我还能用外部类的私有属性i="+i);
            }
        };
        inter.inter();
        //基于类的匿名内部类
        /*OtherClass otherClass = new OtherClass("常"){//用新对象otherClass接收内部类实例化的对象
            @Override
            public void test1() {
                System.out.println("\n重写了外部类的方法");
            }
        };
        otherClass.test1();*/
        new OtherClass("常"){//只用类里的方法,都不用对象接收了,本身看成对象.方法即可
            @Override
            public void test1() {
                System.out.println("\n重写了外部类的方法");
            }
        }.test1();
    }
}
interface Inter{//接口
    public abstract void inter();//接口中抽象方法
}
class OtherClass{//其他外部类
    public OtherClass(String str) {//其他外部类的有参构造器
        System.out.println("其他外部类的构造器\t\t"+str);
    }
    public void test1(){//其他外部类的方法
        System.out.println("其他外部类的方法");
    }
}

实用场景:

当做实参直接传递,简洁高效(就是可能别人看不懂)

public class AnonymousTest {//匿名内部类使用场景
    public static void main(String[] args) {
        //当做实参直接传递,不用实现接口并创建对象了
        test(new TestInter() {
            @Override
            public void show() {
                System.out.println("重写接口里的show方法");
            }
        });
        test(new TestInter() {//相当又写了个类,实现了接口的方法
            @Override
            public void show() {
                System.out.println("我又重写接口里的show方法");
            }
        });
    }
    //静态方法,形参是接口类型
    public static void test(TestInter testInter){
        testInter.show();
    }
}
interface TestInter{//接口
    void show();
}
成员内部类

位置:属于外部类的一部分,和属性方法构造器并列的位置

特点:(看做一个成员)

  1. 没有statc修饰
  2. 在成员内部类的方法或代码块中可直接访问外部类的成员和方法(含私有)
  3. 外部类可直接实例化内部类对象,然后使用内部类的资源
  4. 其他外部类不能直接使用,可以通过外部类实例化内部类对象,然后使用内部类的资源
  5. 可以添加任意访问权限修饰符(public…)
  6. 作用域和外部其他成员一样,在整个外部类
public class MemberInnerClass {//成员内部类使用
    public static void main(String[] args) {
        Other other = new Other();
        other.test();//1.通过外部类的test方法(方法里实例化成员内部类,调用方法)

        Other other2 = new Other();
        Other.Inner inner = other2.new Inner();//2.通过外部类实例化成员内部类
    }
}
class Other{
    private int i = 100;//外部类的私有属性
    public String name = "常";
    private void other(){//外部类的私有方法
        System.out.println("我是外部类私有方法");
    }
    class Inner{//成员内部类,直接放在成员的位置!!
        public void show(){//直接可以使用外部类的成员(包括私有的)
            System.out.println("外部类的i="+i+",名字叫"+name);
            other();//使用外部类私有的方法
        }
    }
    public void test(){
        Inner inner = new Inner();
        inner.show();//使用成员内部类的方法
    }
}
静态内部类

位置:属于外部类的一部分,和属性方法构造器并列的位置

特点:

  1. 有statc修饰
  2. 在成员内部类的方法或代码块中只能访问外部类的静态成员和方法(含私有),不能访问非静态成员
  3. 外部类和其他外部类能直接实例化内部类,然后使用内部类的资源(其他内部类通过外部类.内部类即可实例化对象,看下面代码)
  4. 可以添加任意访问权限修饰符(public…)
  5. 作用域和外部其他成员一样,在整个外部类
public class StaticInnerClass {
    public static void main(String[] args) {
        OtherClasses os = new OtherClasses();
        os.other();//外部类里实例化内部类并调用方法了

        OtherClasses.Inner inner = new OtherClasses.Inner();//直接通过外部类.内部类使用
        inner.show();
    }
}
class OtherClasses{//外部类
    private int i = 100;//外部类的私有属性
    private static String name = "常";
    static class Inner{//静态内部类,放在外部类的成员位置,static修饰
        public void show(){
            System.out.println("外部类的静态成员:"+name);
        }
    }
    public void other(){
        Inner inner = new Inner();
        inner.show();
    }
}
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值