• 【Java】封装、继承、多态


    面向对象的重要特征:封装、继承、多态;

    面向对象的语言的语言并不止Java,C++也是面向对象的语言;


    访问限定符

    • public:在哪里都可以使用(公开的);
    • private:仅在当前类可以使用(私有的);
    • 不写任何限定符:只能在当前包使用(默认的);
    • protected:可以在当前包使用,也可以在不同包的子类中使用(被保护的);

    封装

    封装:就是将类的实现细节进行隐藏;仅对外公开接口来和对象进行交互;

    实现封装后:在当前类外就无法直接拿到某个被封装的字段或方法(被private所修的字段或方法);


    static关键字

    static修饰成员变量(静态变量)

    被static所修饰的成员变量不属于对象——不能使用对象的引用来访问成员变量;

    被static修饰的成员变量属于当前类,是类变量——所以可以通过类的引用进行访问;

    静态的只能是成员变量,不能是局部变量(Java中没有全局变量的说法);


    static修饰成员方法

     static修饰的成员方法叫做静态方法,是类方法,不属于对象;

    静态方法可以通过类访问,也可以通过对象访问(不建议);

    静态方法中不能访问任何非静态成员变量;

    静态方法中不能调用任何非静态方法;


    代码块

    使用大括号{}定义的代码,称之为代码块;

    1. 普通代码块
    2. 构造代码块(也叫实例代码块)
    3. 静态代码块
    4. 同步代码块(多线程学)

    构造代码块:

    • 只有在创建对象时才会被执行;

    静态代码块:

    • 一般用于初始化静态成员变量;
    • 类中有多个静态代码块,则会一次执行(合并);
    • jvm在加载类时就会为静态成员变量开辟空间并初始化;

    内部类和外部类

    在一个类1的内部有一个类2,则类1称为外部类,类2称为内部类;

    内部类和外部类共用一个Java源文件,但是编译后内部类会形成一个单独的字节码文件;

    内部类分类:

    实例内部类:
    • 在实例内部类中可以直接访问外部类中的任何成员;
    • 当内部类和外部类成员同名时,优先使用内部类的成员(局部优先);
    • 内部类和外部类成员同名时,通过外部类名.this.成员名进行访问;
    • 访问内部类的成员必须要创建实例化对象;


    静态内部类 :

    被static所修饰的内部类就是静态内部类;

    静态内部类中只能访问外部类中的静态成员;

    创建静态内部类对象时,不需要先创建外部类对象;


     继承

    • 继承的定义:将某些公共性质抽取出来,将这些共性单独写一个类(父类);
    • 继承的作用:将这些共性写成一个类实现了代码的复用;
    • 继承的使用:当子类与父类之间存在is-a关系时,就可以使用继承;

    extends关键字

    子类 extends 父类;// extends关键字属于继承关键字;

    • 子类会将父类的属性和方法继承过来;
    • 父类被static所修饰的方法不会被继承(子类继承的是父类的对象,被static修饰的属于类);
    • 子类不能继承父类的构造方法;
    1. class Animal { // 父类->将子类中共有的性质写出来
    2. private String name;
    3. private int age;
    4. public void setName(String name) {
    5. this.name = name;
    6. }
    7. public String getName() {
    8. return name;
    9. }
    10. public void eat(Animal this) {
    11. System.out.println(this.name + " 正在吃饭");
    12. }
    13. public void sleep(Animal this) {
    14. System.out.println(this.name + " 正在睡觉");
    15. }
    16. private void play(Animal this) { // 被private或者static所修饰的无法被继承
    17. System.out.println(this.name + " 正在玩耍");
    18. }
    19. }
    20. class Dog extends Animal { // 子类Dog继承了父类Animal的属性和方法
    21. private String color;
    22. public void setColor(String color) {
    23. this.color = color;
    24. }
    25. public String getColor() {
    26. return color;
    27. }
    28. public void skin(Dog this) { // 这子类中调用了父类的方法getName();
    29. System.out.println(this.getName() + " 是" + this.getColor());
    30. }
    31. }
    32. public class Test{
    33. public static void main(String[] args) {
    34. Dog dog = new Dog();
    35. dog.setName("二哈");
    36. dog.setColor("黄色");
    37. dog.eat(); // 父类的方法
    38. dog.skin(); // 子类自己的方法
    39. }
    40. }

    super和this关键字

    • super关键字:就是告诉编译器指定访问父类的成员属性和方法;
    • this关键字:表示访问当前类的成员属性和方法;(子类继承父类,所以拥有了父类的属性和方法,当this访问时先访问自己的,如果自己没有再访问父类的;)

     super关键字和this关键字,不能出现在static所修的的方法中;

    super.成员变量; // 访问父类成员变量

    super.成员方法;// 访问父类成员方法

    super(); // 调用父类构造方法

    • 子类实例化对象的时候,就必须将父类的构造方法进行初始化(在继承关系下,一定是先有父再有子);
    • 当我们没写构造方法的时候,编译器会为我们生成一个不带参数的构造方法;
    • super()和this()不能同时存在,因为他们两个都必须方法构造方法的第一行;
    1. class Animal { // 父类->将子类中共有的性质写出来
    2. private String name;
    3. private int age;
    4. public Animal(String name, int age) { // 父类的构造方法
    5. this.name = name;
    6. this.age = age;
    7. }
    8. public void setName(String name) {
    9. this.name = name;
    10. }
    11. public String getName() {
    12. return name;
    13. }
    14. public void eat(Animal this) {
    15. System.out.println(this.name + " 正在吃饭");
    16. }
    17. public void sleep(Animal this) {
    18. System.out.println(this.name + " 正在睡觉");
    19. }
    20. private void play(Animal this) {
    21. System.out.println(this.name + " 正在玩耍");
    22. }
    23. }
    24. class Dog extends Animal { // 子类Dog继承了父类Animal的属性和方法
    25. private String color;
    26. public Dog(String name, int age, String color) { // 子类的构造方法
    27. super(name, age); // 调用父类构造方法
    28. this.color = color;
    29. }
    30. public void setColor(String color) {
    31. this.color = color;
    32. }
    33. public String getColor() {
    34. return color;
    35. }
    36. public void skin(Dog this) { // 使用super.getName()是调用了父类的方法;
    37. System.out.println(super.getName() + " 是" + this.getColor());
    38. }
    39. }
    40. public class Test{
    41. public static void main(String[] args) {
    42. Dog dog = new Dog("阿黄", 2, "红色");
    43. dog.eat();
    44. dog.skin();
    45. // Dog dog = new Dog();
    46. // dog.setName("二哈");
    47. // dog.setColor("黄色");
    48. // dog.eat(); // 父类的方法
    49. // dog.skin(); // 子类自己的方法
    50. }
    51. }

     

    代码执行顺序、final关键字

    父类的静态->子类的静态->父类的实例->父类的构造->子类的实例->子类的构造

    • 被final所修饰的变量称为常量;
    • 被final修饰的类不能被继承;

     

    多态

    • 多态的定义:不同的对象去完成同一个行为产生了不同的效果就成为多态;
    • 多态的实现条件:继承、向上转型、重写;
    • 向上转型:父类引用接收子类对象;(父类引用只能调用自己的方法,不能调用子类的)
    • 重写:在子类中写一个和父类一样的方法;(方法名相同、返回值相同、参数列表相同(个数、顺序、类型);)

    向上转型、重写

    向上转型: 就是子类对象赋值给父类的引用(父类引用子类对象);

    • 子类 对象1 = new 子类(); 父类 对象 = 对象1;
    • 向上转型就不能调用子类特有的方法;
    • 向上转型的三种:1、直接赋值;2、方法参数的传递;3、方法返回值

    向下转型:强制类型转换,需要进行判断,使用instanceof关键字进行判断;

    重写(覆盖、覆写):在子类中重写父类中的方法,在这个过程中会发生动态绑定

    • 重写:返回值、方法名、参数列表(个数、顺序、类型)都相同;
    • 被static修的方法不能被重写;
    • 被private所修饰的方法也不能被重写;(因为这个方法只能在当前类使用)
    • 重写权限:子类方法权限大于等于父类方法权限;

    动态绑定:在编译的时候不确定调用哪个方法,在运行的时候才知道调用的哪个方法(在方法重写发生);

    静态绑定:静态绑定:指的是在编译的时候就已经知道调用哪个方法了(在方法重载发生);

    1. class Animal { // 父类->将子类中共有的性质写出来
    2. private String name;
    3. private int age;
    4. public Animal(String name, int age) { // 父类的构造方法
    5. this.name = name;
    6. this.age = age;
    7. }
    8. public void setName(String name) {
    9. this.name = name;
    10. }
    11. public String getName() {
    12. return name;
    13. }
    14. public void eat(Animal this) {
    15. System.out.println(this.name + " 正在吃饭");
    16. }
    17. public void sleep(Animal this) { // 在子类中重写一个sleep方法,实现动态绑定
    18. System.out.println(this.name + " 正在睡觉");
    19. }
    20. private void play(Animal this) {
    21. System.out.println(this.name + " 正在玩耍");
    22. }
    23. }
    24. class Dog extends Animal { // 子类Dog继承了父类Animal的属性和方法
    25. private String color;
    26. public Dog(String name, int age, String color) { // 子类的构造方法
    27. super(name, age); // 调用父类构造方法
    28. this.color = color;
    29. }
    30. public void setColor(String color) {
    31. this.color = color;
    32. }
    33. public String getColor() {
    34. return color;
    35. }
    36. public void skin(Dog this) { // 使用super.getName()是调用了父类的方法;
    37. System.out.println(super.getName() + " 是" + this.getColor());
    38. }
    39. @Override // @Override是注解,起到编译器的作用
    40. public void sleep(Dog this) { // 这就是在子类中重写的sleep方法(动态绑定在重写时发生)
    41. System.out.println(super.getName() + " 没有在睡觉");
    42. }
    43. }
    44. public class Test{
    45. public static void main(String[] args) {
    46. Animal dog = new Dog("狗蛋", 3, "绿色");
    47. // 父类引用子类对象,这就是向上转型
    48. dog.eat(); // 父类调用自己的方法
    49. //dog.skin(); // 父类无法调用子类的方法,所以这行代码是错的
    50. dog.sleep(); // 因为sleep方法进行了重写,所以此时调用子类中的sleep
    51. }
    52. }

    避免在构造方法中调用重写方法

    父类构造方法中调用重写方法,也会发生动态绑定;意味着构造方法内也会发生动态绑定;

    代码执行顺序:父类实例->父类构造->子类实例->子类构造;

    new:1、分配内存空间;2、调用合适构造方法;

    在构造方法中调用重写方法,这样可能会导致变量没有实例化;

  • 相关阅读:
    Matlab论文插图绘制模板第124期—三维气泡图
    python经典百题之围圈报数
    Google Cloud X Kyligence|如何从业务视角管理数据湖?
    [附源码]java毕业设计社区新冠疫苗接种管理系统
    pycharm连接MySql数据库,新建表creat table、删除表drop table、查询表select、插入数据insert
    关于表单校验,:rules=“loginRules“
    写个简单的管理数组指针的智能指针
    【LeetCode高频100题】1 - ?
    Springboot实现国际化以及部署Linux不生效问题
    MyBatis原理分析手写持久层框架
  • 原文地址:https://blog.csdn.net/2201_75406088/article/details/134232488