Java进阶

Java进阶

面向对象高级

static

1、static是什么

static 是 静态 可以用于修饰 变量,方法,代码块,内部类

注意:是内部类:在一个类中声明的类,static无法修饰最外层的类。

public class OuterClass {
   int a=0;
  private   int b=0;
    // 静态嵌套类
    public static class StaticNestedClass {

        // 静态嵌套类的成员
        public void display(OuterClass o) {
            System.out.println("Inside StaticNestedClass"+o.b);
            System.out.println("Inside StaticNestedClass"+o.a);
        }
    }

    public static void main(String[] args) {
        // 通过外部类来创建静态嵌套类的实例
        OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
        nestedObject.display(new OuterClass());
        //单独创建静态嵌套类的实例
          StaticNestedClass nestedObject2 = new StaticNestedClass();
        nestedObject2.display(new OuterClass());
    }
}

静态嵌套类有以下几个特点:

  • 它们是独立于外部类实例的,这意味着你可以不创建外部类的实例而直接创建静态嵌套类的实例。

  • 静态嵌套类可以通过外部类的实例直接访问外部类的所有成员,包括私有的成员。

  • 创建静态嵌套类的对象不会影响外部类的状态。

    不会影响外部类的状态

    • 实例变量:静态嵌套类的实例化和使用不会改变外部类的实例变量的值。
    • 方法执行:静态嵌套类的实例化和使用不会影响外部类的方法的执行结果。
2、static修饰的成员变量叫什么? 怎么使用?有啥特点 ?
public class StaticClass {
    static  int a;
    static  int b;
    public static void main(String[] args) {
        System.out.println(StaticClass.a);
        System.out.println(StaticClass.b);
        //特点会被类的所有变量共享
        a=10;
        StaticClass staticClass1=new StaticClass();
        StaticClass staticClass2=new StaticClass();
        StaticClass staticClass3=new StaticClass();
        System.out.println("对象1:"+staticClass1.a);//10
        System.out.println("对象2:"+staticClass2.a);//10
        System.out.println("对象3:"+staticClass3.a);
        //改变其中一个对象a的值其他对象的a都会改变
        staticClass1.a=20;
        //
        System.out.println("--------改变后---------");
        System.out.println("对象:1"+staticClass1.a);//20
        System.out.println("对象:2"+staticClass2.a);//20
        System.out.println("对象:3"+staticClass3.a);//20
    }
}
对象110
对象210
对象310
--------改变后---------
对象120
对象220
对象320
  • static修饰的成员变量叫类变量(静态成员变量)
  • 使用类名.变量名称使用StaticClass.a
  • 特点:属于类,与类一起加载一次,在内存中只有一份,会被类的所有对象共享
3、static注意事项
  • 类方法中可以直接访问类的成员,不可以直接访问实例成员。
  • 实例方法中既可以直接访问类成员,也可以直接访问实例成员。
  • 实例方法中可以出现this关键字,类方法中不可以出现this关键字的。

面向对象三大特征

一、封装
定义

封装是指将数据(属性)和操作数据的方法绑定在一起作为一个单独的单元(即类),并且尽可能隐藏类的内部实现细节,只暴露对外接口给外部使用。

目的
  • 数据保护:防止外部直接访问或修改对象的内部状态,提高安全性。
  • 代码复用性:通过提供公共方法来操作私有数据成员,使得代码更加模块化,易于重用。
  • 维护简便:当需要改变类的内部实现时,只要不改变其对外提供的接口,就不会影响到其他部分的代码。
实现方式
  1. 访问修饰符:Java提供了四种不同的访问级别,分别是publicprotectedprivate和默认(无关键字)。通常将类中的字段设置为private,以防止外部直接访问。

  2. getter和setter方法:为了允许外部安全地读取或修改私有字段,可以通过提供公共的getter(获取器)和setter(设置器)方法来间接访问这些字段。

  3. final关键字:可以使用final关键字来阻止类的继承或者方法的覆盖,从而保护类或方法不被更改。

  4. 内部类:在某些情况下,可以使用内部类来封装数据和行为,这样只有包含该内部类的外部类才能访问它。

    public class Person {
        // 私有字段
        private String name;
        private int age;
    
        // 默认构造函数
        public Person() {}
    
        // 带参数的构造函数
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        // Getter for name
        public String getName() {
            return name;
        }
    
        // Setter for name
        public void setName(String name) {
            this.name = name;
        }
    
        // Getter for age
        public int getAge() {
            return age;
        }
    
        // Setter for age
        public void setAge(int age) {
            if (age > 0) { // 添加简单的验证逻辑
                this.age = age;
            } else {
                System.out.println("年龄必须大于0");
            }
        }
    }
    
二、继承
定义

继承是面向对象编程中一个重要的概念,它允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。通过继承,子类可以获得父类的所有非私有成员(字段和方法),并且可以添加新的方法和字段,或者重写父类的方法以实现多态性。

目的
  • 代码复用:子类可以直接使用父类已经定义好的属性和方法,避免重复编写相同的代码。
  • 层次结构:通过继承可以建立类之间的层次关系,使得类的设计更加清晰和合理。
  • 扩展性:子类可以在不修改父类的情况下增加新的功能,提高了代码的灵活性和可扩展性。
实现方式

extends:用于声明一个类继承自另一个类。例如:

public class B{
    
}
public class A extends B {
    // 子类的定义
}
访问控制
访问修饰符本类同一个包中的类子孙类任意类
public
privte
默认(没有填写访问修饰符)
protected
方法重写
  • 子类可以重写父类的方法以提供特定的实现。
  • 使用@Override注解可以明确表示这是一个重写方法,有助于编译器检查错误。
  • 重写方法的访问权限不能比父类的方法更严格。
子类访问其他成员的特点
就近原则
  • 先子类局部范围找。
  • 然后子类成员范围找。
  • 然后父类成员范围找,如果父类范围还没有找到则报错。
子父类出现了重名的成员,会优先使用子类的,想要使用父类的

可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法

子类构造器的特点
  • 子类的全部构造器,都会先调用父类的构造器,再执行自己使用super(…)调用,默认存在。
  • 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(….),指定去调用父类的有参数构造器。
  • this(…)和super(…)使用时的注意事项:this(…) 、super(…) 都只能放在构造器的第一行,两者不能共存。
示例
// 父类 Animal
public class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    public void eat() {
        System.out.println(name + " is eating.");
    }

    public void sleep() {
        System.out.println(name + " is sleeping.");
    }
}

// 子类 Dog
public class Dog extends Animal {
    public Dog(){
        this("哈哈")
    }
    public Dog(String name) {
        super(name); // 调用父类的构造器
    }

    @Override
    public void eat() {
        System.out.println(name + " is eating dog food.");
    }

    public void bark() {
        System.out.println(name + " is barking.");
    }
}

// 测试类
public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("Buddy");
        myDog.eat();   // 输出: Buddy is eating dog food.
        myDog.sleep(); // 输出: Buddy is sleeping.
        myDog.bark();  // 输出: Buddy is barking.
    }
}
多次继承
  • Java 不支持多重继承(一个类不能继承多个类),但可以通过接口实现类似的功能。
注意事项
  • 过度继承:过多的继承层次可能导致代码复杂性和维护难度增加。
  • 继承与组合:在某些情况下,使用组合(Composition)而不是继承可能更合适。组合是指在一个类中包含另一个类的对象,而不是继承它的行为。
三、多态
定义

多态是指同一个接口或引用类型可以表示不同的实际类型的能力。多态使得子类对象可以被当作父类对象来使用,从而增加了代码的灵活性和可扩展性。Java中的多态主要通过方法重写(Method Overriding)和接口实现(Interface Implementation)来实现。

目的
  • 代码复用:通过多态,可以使用统一的接口来处理不同类型的对象,减少了代码的冗余。
  • 灵活性:多态使得程序可以在运行时决定具体的行为,增强了代码的动态性。
  • 扩展性:新增加的子类可以很容易地集成到现有的系统中,而不需要修改已有的代码。
类型
编译时多态(静态多态):通过方法重载(Method Overloading)实现。

方法重载

  • 方法重载是指在同一个类中,可以有多个同名但参数列表不同的方法。
  • 编译器根据传入参数的不同来决定调用哪个方法。
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }
}
运行时多态(动态多态):通过方法重写(Method Overriding)和接口实现(Interface Implementation)实现。

方法重写

  • 方法重写是指子类重新定义父类中已经存在的方法。
  • 使用@Override注解可以明确表示这是一个重写方法,有助于编译器检查错误。
  • 重写方法的访问权限不能比父类的方法更严格。
public class Animal {
    public void makeSound() {
        System.out.println("Some generic sound");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark");
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow");
    }
}

接口实现 (Interface Implementation)

  • 接口定义了一组方法,但没有具体的实现。
  • 类可以通过实现接口来提供这些方法的具体实现。
  • 实现接口也可以实现多态。
public interface Animal {
    void makeSound();
}

public class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark");
    }
}

public class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myDog.makeSound(); // 输出: Bark
        myCat.makeSound(); // 输出: Meow
    }
}

注意事项

  • 向上转型:将子类对象赋值给父类引用的过程称为向上转型,这是隐式的,不需要强制转换。
  • 向下转型:将父类引用转换为子类对象的过程称为向下转型,这是显式的,需要强制转换,并且需要确保引用的实际对象是子类的实例,否则会抛出ClassCastException异常。

final关键字

定义

final是一个修饰符,可以应用于类、方法和变量,具有不同的作用和用途。

final修饰变量
  • 定义final修饰的变量是一个常量,一旦被赋值就不能再被改变。
  • 用途:用于定义常量,确保数据的不可变性,提高代码的安全性和可读性。
public class Constants {
    public final int MAX_VALUE = 100;

    public Constants() {
        // 试图改变final变量的值会导致编译错误
        // MAX_VALUE = 200; // 编译错误
    }

    public static void main(String[] args) {
        Constants c = new Constants();
        // 试图改变final变量的值会导致编译错误
        // c.MAX_VALUE = 200; // 编译错误
        System.out.println(c.MAX_VALUE); // 输出: 100
    }
}
final修饰方法
  • 定义final修饰的方法不能被子类重写。
  • 用途:防止子类改变父类的方法实现,确保某些方法的行为在所有子类中保持一致。
public class BaseClass {
    public final void display() {
        System.out.println("This is a final method.");
    }
}

public class DerivedClass extends BaseClass {
    // 试图重写final方法会导致编译错误
    // @Override
    // public void display() {
    //     System.out.println("Trying to override final method.");
    // }
}

public class Main {
    public static void main(String[] args) {
        DerivedClass obj = new DerivedClass();
        obj.display(); // 输出: This is a final method.
    }
}
final 修饰类
  • 定义final修饰的类不能被继承。
  • 用途:防止类被子类化,确保类的完整性和安全性,适用于那些不应该被扩展的类。
public final class FinalClass {
    public void display() {
        System.out.println("This is a final class.");
    }
}

// 试图继承final类会导致编译错误
// public class DerivedClass extends FinalClass {
// }

public class Main {
    public static void main(String[] args) {
        FinalClass obj = new FinalClass();
        obj.display(); // 输出: This is a final class.
    }
}
final参数
  • 定义final修饰的参数在方法体内不能被修改。
  • 用途:确保方法体内的参数值不会被改变,提高代码的安全性和可读性。
public class FinalParameterExample {
    public void display(final String message) {
        // 试图修改final参数会导致编译错误
        // message = "New message"; // 编译错误
        System.out.println(message);
    }

    public static void main(String[] args) {
        FinalParameterExample example = new FinalParameterExample();
        example.display("Hello, World!"); // 输出: Hello, World!
    }
}
final 对象的不可变性
  • 定义:如果一个对象被声明为final,那么这个对象的引用不能被改变,但对象内部的状态仍然可以改变。
  • 用途:确保对象引用的不变性,但需要注意对象内部的状态是否也应该是不可变的。
public class FinalObjectExample {
    public final StringBuilder sb = new StringBuilder("Initial");

    public void changeStringBuilder() {
        // 试图改变final对象的引用会导致编译错误
        // sb = new StringBuilder("New"); // 编译错误
        // 但可以改变对象内部的状态
        sb.append(" Changed");
    }

    public static void main(String[] args) {
        FinalObjectExample example = new FinalObjectExample();
        example.changeStringBuilder();
        System.out.println(example.sb.toString()); // 输出: Initial Changed
    }
}

抽象类

定义
  • 抽象类:使用abstract关键字修饰的类。
  • 抽象方法:使用abstract关键字修饰的方法,没有具体实现(即没有方法体)。
特点
  1. 不能实例化:抽象类不能直接创建对象,只能被继承。
  2. 包含抽象方法:抽象类可以包含抽象方法,子类必须实现这些抽象方法。
  3. 包含具体方法:抽象类可以包含具体方法,子类可以直接继承这些方法。
  4. 构造器:抽象类可以有构造器,主要用于初始化子类对象。
  5. 普通成员变量:抽象类可以包含普通成员变量。
用途
  • 提供模板:定义一个类的框架,规定子类必须实现的某些方法。
  • 代码复用:提供一些通用的方法实现,供子类继承和使用。
  • 多态:通过抽象类实现多态,增强代码的灵活性和扩展性。
示例

假设我们有一个抽象类Animal,它定义了一个抽象方法makeSound,以及一个具体方法eat。然后我们定义两个子类DogCat,它们分别实现了makeSound方法。

// 抽象类 Animal
public abstract class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    // 抽象方法
    public abstract void makeSound();

    // 具体方法
    public void eat() {
        System.out.println(name + " is eating.");
    }
}

// 子类 Dog
public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " says: Bark");
    }
}

// 子类 Cat
public class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " says: Meow");
    }
}

// 测试类
public class Main {
    public static void main(String[] args) {
        // 不能创建抽象类的实例
        // Animal animal = new Animal("Generic Animal"); // 编译错误

        Animal myDog = new Dog("Buddy");
        Animal myCat = new Cat("Whiskers");

        myDog.makeSound(); // 输出: Buddy says: Bark
        myDog.eat();       // 输出: Buddy is eating.

        myCat.makeSound(); // 输出: Whiskers says: Meow
        myCat.eat();       // 输出: Whiskers is eating.
    }
}
详细解释
  1. 抽象类 Animal
    • 包含一个受保护的成员变量name
    • 包含一个构造器,用于初始化name
    • 包含一个抽象方法makeSound,子类必须实现这个方法。
    • 包含一个具体方法eat,子类可以直接继承这个方法。
  2. 子类 DogCat
    • 都继承了抽象类Animal
    • 都实现了抽象方法makeSound,提供了具体的实现。
    • 都可以调用继承自Animal的具体方法eat
注意事项
  • 抽象类不能实例化:不能直接创建抽象类的实例,只能通过子类来实例化。
  • 抽象方法必须被实现:子类必须实现抽象类中的所有抽象方法,除非子类也是抽象类。
  • 抽象类可以包含具体方法:抽象类不仅可以包含抽象方法,还可以包含具体方法和成员变量。

接口

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

love.南亭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值