Java——面向对象进阶(二)

06-28 1547阅读

Java——面向对象进阶(二)

前言:

多态,包,final关键字,权限修饰符和代码块


文章目录

  • 一、多态
    • 1.1 概念
    • 1.2 多态存在条件
    • 1.3 多态中调用成员的特点
    • 1.4 instanceof关键字
    • 二、包
    • 三、权限修饰符
    • 四、final 关键字
      • 4.1 修饰类
      • 4.2 修饰方法
      • 4.3 修饰变量
      • 五、代码块
        • 5.1 局部代码块
        • 5.2 静态代码块
        • 5.3 构造代码块

          一、多态

          1.1 概念

          首先我们要了解一下多态性和多态,这是两个不同的概念,多态性包括很多,例如运行时多态,编译时多态性等,而多态是具体的多态性实现。面向对象中的多态指的是运行时多态性的实现。

          运行时多态: 方法的重写是运行时多态性的一种体现。同类型的对象,表现出不同的形态,即子类可以重写父类的方法,通过父类引用指向子类对象时,调用子类的方法实现。

          1.2 多态存在条件

          多态有以下的存在条件:

          1. 子类必须继承自同一个父类或者实现同一个接口
          2. 有方法重写
          3. 父类类型的引用指向子类对象。

          1.3 多态中调用成员的特点

          特点:

          • 变量调用:静态绑定(早期绑定),这意味着,即使引用类型是父类类型,访问属性时仍然使用父类中定义的变量。如果父类中没有这个变量,会编译失败。

            class Animal {
                String name = "Animal";
                void makeSound() {
                    System.out.println("Animal makes a sound");
                }
            }
            class Dog extends Animal {
                String name = "Dog";
                @Override
                void makeSound() {
                    System.out.println("Dog barks");
                }
            }
            public class Main {
                public static void main(String[] args) {
                    Animal myDog = new Dog();
                    
                    System.out.println(myDog.name); // 输出:Animal
                    myDog.makeSound(); // 输出:Dog barks
                }
            }
            
          • 方法调用:动态绑定(后期绑定),方法调用在运行时而不是在编译时决定,这意味这调用的方法要看实际对象的类型。调用的方法一定要是重写的方法。

            class Animal {
                void makeSound() {
                    System.out.println("Animal makes a sound");
                }
            }
            class Dog extends Animal {
                @Override
                void makeSound() {
                    System.out.println("Dog barks");
                }
            }
            class Cat extends Animal {
                @Override
                void makeSound() {
                    System.out.println("Cat meows");
                }
            }
            public class Main {
                public static void main(String[] args) {
                	//父类类型的引用指向子类对象
                    Animal myDog = new Dog();
                    Animal myCat = new Cat();
                    myDog.makeSound(); // 输出:Dog barks
                    myCat.makeSound(); // 输出:Cat meows
                }
            }
            

            1.4 instanceof关键字

            instanceof 关键字是 Java 中用于测试对象是否为某个特定类或其子类的实例的重要工具。它返回一个布尔值,指示对象是否是指定类或接口的一个实例。instanceof 关键字常用于安全地进行向下转型(将父类引用转换为子类引用)之前的类型检查。

            instanceof 的语法

            object instanceof ClassName
            

            其中,object 是要进行检查的对象,ClassName 是要检查的类或接口。

            class Animal {
            }
            class Dog extends Animal {
            }
            public class Main {
                public static void main(String[] args) {
                    Animal myAnimal = new Dog();
                    // 检查 myAnimal 是否是 Dog 类的实例
                    if (myAnimal instanceof Dog) {
                        System.out.println("myAnimal 是 Dog 类的一个实例");
                    } else {
                        System.out.println("myAnimal 不是 Dog 类的一个实例");
                    }
                    // 检查 myAnimal 是否是 Animal 类的实例
                    if (myAnimal instanceof Animal) {
                        System.out.println("myAnimal 是 Animal 一个的实例");
                    } else {
                        System.out.println("myAnimal 不是 Animal 一个的实例");
                    }
                }
            }
            

            输出

            myAnimal 是 Dog 类的一个实例
            myAnimal 是 Animal 一个的实例
            

            除此之外,JDK14提出了新特性,

            object instanceof ClassName newObject
            

            首先判断对象 object 存储的数据是不是 ClassName 类型,如果是,则返回true,并转换为 ClassName 类型的newObject 对象。


            二、包

            包(package) 是用于组织类和接口的一种机制。包提供了一种命名空间管理功能,可以避免命名冲突,并且有助于组织大型项目的代码结构。使用包还可以控制访问权限,限制某些类和接口只能在同一个包中访问。操作如下:

            Java——面向对象进阶(二)

            1. 在类中声明包

              package com.example.myapp;
              
            2. 导入包

              使用 import 关键字导入其他包中的类或接口。

              import com.example.myapp.User;
              

              如果要导入整个包,可以使用通配符 *:

              import com.example.myapp.*;
              

            在不同包下使用相同类:

            //使用全类名的形式即可。
            //全类名:包名 + 类名
            //拷贝全类名的快捷键:选中类名crtl + shift + alt + c 或者用鼠标点copy,再点击copy Reference
            com.example.demo1.Student s1 = new com.example.demo1.Student();
            com.example.demo2.Student s2 = new com.example.demo2.Student();
            

            三、权限修饰符

            ​ 在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限。

            • public:公共的,所有地方都可以访问。

            • protected:本类 ,本包,其他包中的子类都可以访问。

            • 默认(没有修饰符):本类 ,本包可以访问。注意:默认是空着不写,不是default

            • private:私有的,当前类可以访问。

              类内部同一包不同包中的子类不同包的无关类
              public++++
              protected+++
              默认++
              private+

              四、final 关键字

              使用final 关键字,表示修饰的内容不可变。

              • final 变量:值初始化后不可改变,即有且仅能被赋值一次。
              • final 方法:不能被子类重写。
              • final 类:不能被继承。

                4.1 修饰类

                final 类不能被继承,确保类的完整性。

                public final class FinalClass {
                    // 类内容
                }
                // 编译错误,无法继承 final 类
                // public class SubClass extends FinalClass {
                // }
                

                4.2 修饰方法

                final 方法不能被子类重写,保证方法行为不被修改。

                public class ParentClass {
                    public final void finalMethod() {
                        System.out.println("This method cannot be overridden");
                    }
                }
                public class ChildClass extends ParentClass {
                    // 编译错误,无法重写 final 方法
                    // public void finalMethod() {
                    //     System.out.println("Trying to override");
                    // }
                }
                

                4.3 修饰变量

                1. 局部变量

                  必须在使用前初始化。

                  public void myMethod() {
                      final int localVar;
                      localVar = 10;
                      //localVar = 20; 编译错误,无法修改 final 变量
                  }
                  
                2. 成员变量

                  必须在声明时或构造器中初始化。

                  public class MyClass {
                      final int CONSTANT = 10;
                      final int anotherConstant;
                      public MyClass(int value) {
                          this.anotherConstant = value;
                      }
                      public void method() {
                          // CONSTANT = 20; // 编译错误,无法修改 final 变量
                      }
                  }
                  

                注意:final 修饰不同类型时的区别

                1. final 修饰基本数据类型(包括int、char、float、boolean)

                  当 final 修饰基本数据类型变量时,该变量的值在初始化后不可更改。

                  public class FinalExample {
                      public static void main(String[] args) {
                          final int x = 10;
                          // x = 20; // 编译错误,无法修改 final 变量的值
                          System.out.println("Final primitive value: " + x);
                      }
                  }
                  
                2. final 修饰引用数据类型

                  当 final 修饰引用数据类型变量时,该变量的引用在初始化后不可更改,但引用的对象的内容可以更改。

                  public class FinalReferenceExample {
                      public static void main(String[] args) {
                          final StringBuilder sb = new StringBuilder("Hello");
                          // sb = new StringBuilder("World"); // 编译错误,无法更改 final 引用
                          
                          // 可以修改对象的内容
                          sb.append(" World");
                          System.out.println("Final reference value: " + sb.toString());
                      }
                  }
                  

                五、代码块

                在 Java 中,代码块(也称为块)是一组被大括号 {} 包围的语句。代码块分为以下几种类型:构造代码块、静态代码块、局部代码块。每种类型的代码块在程序执行中的作用和执行时机各不相同。

                5.1 局部代码块

                局部代码块是定义在方法中的一组语句,用于限制变量的作用范围。

                public class LocalCodeBlockExample {
                    public static void main(String[] args) {
                        // 局部代码块
                        {
                            int x = 30;
                            System.out.println("Local code block: x = " + x);
                        }
                        
                        // System.out.println(x); // 编译错误,x 作用范围仅限于局部代码块
                    }
                }
                

                5.2 静态代码块

                静态初始化块在类加载时执行一次,用于初始化静态变量。静态初始化块在类加载时执行,而不是在创建实例时执行。

                public class StaticInitializationBlockExample {
                    private static int x;
                    
                    // 静态初始化块
                    static {
                        x = 20;
                        System.out.println("Static initialization block: x = " + x);
                    }
                    
                    public StaticInitializationBlockExample() {
                        System.out.println("Constructor: x = " + x);
                    }
                    
                    public static void main(String[] args) {
                        StaticInitializationBlockExample example = new StaticInitializationBlockExample();
                    }
                }
                //运行结果
                //Static initialization block: x = 20
                //Constructor: x = 20
                

                5.3 构造代码块

                构造块在每次创建类的实例时执行。它可以用来初始化实例变量。

                public class InstanceInitializationBlockExample {
                    private int x;
                    
                    // 实例初始化块
                    {
                        x = 10;
                        System.out.println("Instance initialization block: x = " + x);
                    }
                    
                    public InstanceInitializationBlockExample() {
                        System.out.println("Constructor: x = " + x);
                    }
                    
                    public static void main(String[] args) {
                        InstanceInitializationBlockExample example = new InstanceInitializationBlockExample();
                    }
                }
                //运行结果
                //Instance initialization block: x = 10
                //Constructor: x = 10
                

                Java——面向对象进阶(二)

                如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!

                欢迎大家提出疑问,以及不同的见解。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]