JavaSE(多态、内部类、权限修饰符、代码块)

多态

概述

定义

  • 多态:是指同一行为,对于不同的对象具有多个不同表现形式。
  • 程序中多态:是指同一方法,对于不同的对象具有不同的实现。

前提条件

  • 继承或者实现(决定性条件)
    1.继承:类和类之间的多态
    2.实现:类和接口之间的多态
  • 父类引用指向子类对象(格式体现)
    1.父类型变量接收子类型对象
    2.父类型形参接收子类型实参对象
    3.父类型返回值类型接收子类型对象
  • 方法的重写(意义体现)

实现多态

多态的体现:父类的引用指向它的子类的对象

父类类型 变量名 = new 子类对象;
变量名.方法名();

tips:父类类型:指子类对象继承的父类类型,或者实现的父接口类型。

class Animal{}
class Cat extends Animal{}
class Dog extends Animal{}
clsss Person{}
//测试类:
main(){
    Animal a1 = new Cat();
    Animal a2 = new Dog();
    Animal a3 = new Person();//编译错误,没有继承关系。
}

多态时访问成员的特点

  • 多态时成员变量的访问特点(编译看左边,运行看左边)
    1.父类型变量只能访问父类型变量,不能访问子类型成员变量
    2.子类型变量可以访问自己成员变量及父类的成员变量
Animal a = new Cat();
// a只能访问Animal中的成员变量,编译和运行都看左边
  • 多态时成员放法的访问特点
    1.编译的时候去父类中查找方法,运行的时候去子类中查找方法来执行(非静态方法:编译看左边,运行看右边)
    2.编译的时候去父类中查找方法,运行的时候去父类中查找方法来执行(静态方法:编译看左边,运行看左边)
  • 注意:多态的情况下是无法访问子类独有的方法

多态的几种表现形式

  • 普通父类多态
public class Fu{}
public class Zi extends Fu{}
public class Demo{
    public static void main(String[] args){
        Fu f = new Zi();//左边是一个“父类”
    }
}
  • 抽象父类多态
public abstract class Fu{}
public class Zi extends Fu{}
public class Demo{
    public static void main(String[] args){
        Fu f = new Zi();//左边是一个“父类”
    }
}
  • 父接口多态
public interface A{}
public class AImp implements A{}
public class Demo{
    public static void main(String[] args){
        A a = new AImp();
    }
}

多态的应用场景

public class Demo1 {
    public static void main(String[] args) {
        /*
            多态的应用场景:
                1.变量多态
                2.形参多态
                3.返回值多态
         */
        // 1.变量多态
        Animal anl = new Dog();
        anl.eat();

        // 2.形参多态
        Dog dog = new Dog();
        invokeEat(dog);

        Cat cat = new Cat();
        invokeEat(cat);// 实参赋值给形参: Animal anl = new Cat();

        // 3.返回值多态
        Animal anl2 = getAnimal();// 返回值赋值给变量: Animal anl2 = new Dog()
    }

    //  3.返回值多态
    // 结论:如果方法的返回值类型为父类类型,那么就可以返回该父类对象以及其所有子类对象
    public static Animal getAnimal(){
//        return new Animal();
        return new Dog();
//        return new Cat();
    }

    // 形参多态: 当你调用invokeEat方法的时候,传入Animal类的子类对象
    // Animal anl = dog; ====>  Animal anl = new Dog();
    // 结论:如果方法的参数是父类类型,那么就可以接收所有该父类对象以及其所有子类对象
    // Object类:是java中所有类的父类,所以如果参数为Object类型,那么就可以传入一切类的对象
    public static void invokeEat(Animal anl){
        anl.eat();
    }
}

多态的好处和弊端

  • 好处
    提高了代码的扩展性、灵活性、尤其体现在方法中的参数和返回值
  • 弊端
    多态的情况下,只能调用父类的共性内容,不能调用子类的特有内容
  • 示例
// 父类
public abstract class Animal {  
    public abstract void eat();  
}  
// 子类
class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void catchMouse(){
         System.out.println("猫抓老鼠");  
    }
}  
class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
}

引用类型转换

向上转型

子类类型向父类类型向上转换的过程,这个过程是默认的。

 Aniaml anl = new Cat();  

向下转型

父类类型向子类类型向下转换的过程,这个过程是强制的。

Aniaml anl = new Cat();  
Cat c = (Cat)anl;//向下转型
c.catchMouse();// 可以访问 子类独有的功能,解决多态的弊端

instance of关键字

  • 向下强转有风险,最好在转换前做一个验证
  • 格式
变量名 instanceof 数据类型 
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回falseif( anl instanceof Cat){//判断anl是否能转换为Cat类型,如果可以返回:true,否则返回:false
    Cat c = (Cat)anl;//安全转换
}

内部类

内部类的概述

什么是内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类

成员内部类

  • 概述:定义在类中方法外的类。
  • 定义格式
class 外部类 {
    class 内部类{

    }
}

在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。比如,汽车类Car 中包含发动机类Engine ,这时,Engine就可以使用内部类来描述,定义在成员位置。

  • 示例
class Car { //外部类
    class Engine { //内部类

    }
}

访问特点

  1. 内部类可以直接访问外部类的成员,包括私有成员。
  2. 外部类要访问内部类的成员,必须要建立内部类的对象。
  • 创建内部类对象格式
外部类名.内部类名 对象名 = new 外部类型().new 内部类型()
  • 示例
public class Body {// 外部类

    // 成员变量
    private int numW = 10;

    int num = 100;

    // 成员方法
    public void methodW1(){
        System.out.println("外部类中的methodW1方法...");
    }

    public void methodW2(){
        System.out.println("外部类中的methodW2方法...");
        // 创建内部类对象
        Body.Heart bh = new Body().new Heart();
        // 访问内部类成员变量
        System.out.println("内部类成员变量numN:"+bh.numN);
        // 访问内部类成员方法
        bh.methodN2();
    }

    public class Heart{// 成员内部类
        // 成员变量
        int numN = 20;

        int num = 200;

        // 成员方法
        public void methodN(){
            System.out.println("内部类中的methodN方法...");
            // 访问外部类成员变量
            System.out.println("外部类成员变量:"+numW);
            // 访问外部类成员方法
            methodW1();
        }

        public void methodN2(){
            System.out.println("内部类中的methodN2方法...");
        }

        public void methodN3(){
            int num = 300;
            System.out.println("局部变量num:"+num);// 300
            System.out.println("内部类成员变量num:"+this.num);// 200
            System.out.println("外部类成员变量num:"+Body.this.num);// 100
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        // 测试
        // 创建外部类对象,调用外部类的方法methodW2
        Body body = new Body();
        body.methodW2();

        System.out.println("=======================");

        // 创建内部类对象,调用内部类的methodN方法
        Body.Heart heart = new Body().new Heart();
        heart.methodN();

        System.out.println("=======================");
        heart.methodN3();// 300  200  100
    }
}

匿名内部类

  • 概述
    是内部类的简化写法。它的本质是一个带具体实现的 父类或者父接口的 匿名的 子类对象
  • 示例一
public abstract class Animal {
    public abstract void eat();
}
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头...");
    }
}
public class Test {
    public static void main(String[] args) {
        /*
            - 匿名内部类的概述:本质就是继承了父类或者实现了接口的匿名子类的对象
            - 匿名内部类的格式:
                new 类名\接口名(){
                    方法重写
                };

            - 匿名内部类的作用: 为了简化代码,并没有什么特殊的功能

            需求: 调用Aniaml类的eat()方法
            1.创建一个子类继承Animal类
            2.在子类中重写eat方法
            3.创建子类对象
            4.使用子类对象调用eat方法

            想要调用抽象类中的方法,必须具备以上4步,那能不能减后呢? 可以 使用匿名内部类
         */
        Animal anl1 = new Dog();
        anl1.eat();

        Animal anl2 = new Animal() {
            @Override
            public void eat() {
                System.out.println("Animal子类的eat方法...");
            }
        };
        anl2.eat();
    }
}
  • 示例二
public interface AInterface {
    void method();
}
public class AImp implements AInterface {
    @Override
    public void method() {
        System.out.println("AImp 实现类重写method方法....");
    }
}
public class Demo {
    public static void main(String[] args) {
        /*
             匿名内部类:
                本质是一个继承了父类的匿名子类的对象
                本质是一个实现了接口的匿名实现类的对象

              案例: A接口中有一个抽象方法method(),现在需要调用A接口中的method方法
              思路:
                1.创建一个实现类实现A接口
                2.重写A接口中的抽象方法method()
                3.创建实现类对象
                4.使用实现类对象调用method方法

               想要调用A接口中的method方法,按照传统方式,必须有以上4步,一步都不可少
               前面三步就是为了得到A接口的实现类对象

            现在: 匿名内部类可以表示一个接口的匿名实现类对象,所以,可以直接创建接口的匿名内部类来调用method方法即可
         */
        AInterface a = new AInterface(){
            @Override
            public void method() {
                System.out.println("匿名内部类方式重写method方法....");
            }
        };
        a.method();

        System.out.println("==================");

        AInterface a2 = new AImp();
        a2.method();

        System.out.println("======================");
        AInterface a3 = new AInterface() {
            @Override
            public void method() {
                // 实现
            }
        };
    }
}

权限修饰符

  • 概述
    在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限,public:公共的;protected:受保护的;(空的):默认的;private:私有的
  • 不同权限的访问能力
publicprotected(空的)private
同一类中
同一包中(子类与无关类)
不同包的子类
不同包中的无关类
  • 大小关系
    public > protected > (空的) > private
  • 编写代码时,如果没有特殊的考虑,建议这样使用权限
    1.成员变量使用private,隐藏细节。
    构造方法使用public,方便创建对象。
    成员方法使用public,方便调用方法。

代码块

构造代码块

格式: {}
位置: 类中,方法外
执行: 每次在调用构造方法的时候,就会执行
使用场景: 统计创建了多少个该类对象

例如:
public class Person{
    {
        构造代码块执行了
    }
}

静态代码块

格式:static{}
位置: 类中,方法外
执行: 当类被加载的时候执行,并只执行一次
使用场景: 例如加载驱动,这种只需要执行一次的代码就可以放在静态代码块中         

public class Person {
	private String name;
	private int age;
 //静态代码块
	static{
		System.out.println("静态代码块执行了");
	}
}

局部代码块

格式:{}
位置: 方法中
执行: 调用方法,执行到局部代码块的时候就执行
使用场景: 节省内存空间,没有多大的意义
例如:
public static void main(String[] args) {
     int a = 10;
     //局部代码块
     //局部代码块的作用就是限制变量的作用域,早早的从内存中消失,节约内存
     //但是现在内存不值钱,所以局部代码块没有使用意义
     {
         int b = 20;
     }

     //int a = 30;    //在同一个区域不能定义重名变量
     //不报错,以为作用域不同
     int b = 40;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值