java面向对象学习总结

当谈到面向对象编程时,有的人会说他的三大特征,有的人会说面向对象怎么怎么好,那么什么是对象呢?因此笔者在介绍三大特性前,想先简单说一下什么是对象。

松本行弘在《代码的未来》中说:所谓对象,就是抽象化的数据本身。那么,什么又是抽象呢?

想象一下,你想设计一个可以帮你管理家庭开支的应用。你需要一种方法来表示你的花费,并且能够随时修改和查询它们。这时,你可以创建一个“开支”对象来表示每个花费,它有一个“金额”属性来表示花费的数额,还有一些方法来更改和查询这个数额。

类似于这个例子,面向对象编程中的对象就是我们从现实抽象到代码中创造出来的可爱小伙伴。每个对象都有自己的特征和性格,可以执行一些任务,还可以与其他对象互动。

比如,你可以创建一个“狗”对象。这个对象有一个“名字”属性,一个“跑”方法,一个“叫”方法,还有一些其他的方法和属性,让你能够与这个“狗”对象进行互动,例如给它喂食、散步、以及听它咆哮。

由于笔者资历尚浅所以也没什么深刻的认识,望诸位读者见谅,接下来是对java面向对象一些知识点的介绍。

1.封装

封装是一种将相关数据和方法组合成一个独立单元,并对外部对象隐藏内部实现细节的方式。通过封装,我们可以保护数据的完整性,防止错误的访问和修改。在Java中,我们可以使用访问修饰符(如private、public、protected)来控制成员的访问权限。

示例代码:

public class Person {
    private String name;
    private int age;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
}

在上面的示例中,我们定义了一个Person类,其中name和age字段被声明为private,通过公共的getter和setter方法来访问和修改这些字段的值。通过封装,我们可以控制对name和age的访问,确保数据的安全性。

1.1权限修饰符相关

1.2 this 相关

1.this关键字代表当前对象

        this.属性 操作当前对象的属性

        this.方法 调用当前对象的方法。

2.封装对象的属性的时候,经常会使用this关键字。

3.当getter和setter函数参数名和成员函数名重合的时候,可以使用this区别。如:

public class Person {
    private String name;
    private int age;
    
 
    public void setName(String name) {
        this.name = name;
    }
    
 
    
    public void setAge(int age) {
        this.age = age;
    }
}

2.继承

继承是一种通过扩展已有类来创建新类的机制。通过继承,我们可以重用现有类的代码和行为,并添加新的功能或修改现有功能。在Java中,使用关键字extends来实现继承。

示例代码:

public class Animal {
    public void makeSound() {
        System.out.println("The animal makes a sound");
    }
}

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

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

在上面的示例中,Animal类是一个基类,它有一个makeSound方法。然后,我们创建了一个Dog类和一个Cat类,它们都继承自Animal类,并通过重写makeSound方法来实现自己的声音。通过继承,我们可以避免重复编写相同的代码,并根据需求进行自定义。

注:java中的继承是单继承,即一个类只有一个父类 

3.多态

多态是指在不同的情况下,同一个方法可能表现出不同的行为。在Java中,多态可以通过方法重写和方法重载来实现。方法重写是指子类重写超类的一个或多个方法,而方法重载是指在同一个类中有多个具有不同参数列表的方法。

示例代码:

public class Animal {
    public void makeSound() {
        System.out.println("The animal makes a sound");
    }
}

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

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

public class AnimalTest {
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        
        animal1.makeSound();
        animal2.makeSound();
    }
}

在上面的示例中,Animal类是一个基类,Dog和Cat类分别是子类。通过将Dog和Cat对象分别赋值给Animal类型的变量,我们实现了多态。在运行时,animal1和animal2变量的实际类型决定了调用哪个makeSound方法。这就是多态的一种体现,相同的方法名称,但不同的子类对象会产生不同的行为。

3.1 向上转型和向下转型

 向上转型(隐式/自动类型转换),是小类型转换到大类型。

向下转型(强制类型转换),是大类型转换到小类型(有风险,可能出现数据溢出)

示例代码如下:

class Animal {
    public void makeSound() {
        System.out.println("Animal is make a sound");
    }
}

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

    public void fetch() {
        System.out.println("Dog is fetching");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型

        animal.makeSound(); // 调用的是 Dog 类重写的 makeSound() 方法

        // 向上转型后,无法直接访问 Dog 类的 fetch() 方法
        // animal.fetch(); // 编译错误

        Dog dog = (Dog) animal; // 向下转型

        dog.fetch(); // 可以访问到 Dog 类的 fetch() 方法
    }
}

在上述示例中,Animal 是父类,Dog 是其子类。首先进行了向上转型,将 Dog 对象赋值给 Animal 引用变量 animal。然后,通过父类引用变量调用 makeSound() 方法,由于使用了多态,实际调用的是 Dog 类中重写的 makeSound() 方法。

接着,进行了向下转型,将父类引用变量 animal 强制转换为子类类型 Dog。这样可以再次访问到 Dog 类中特有的 fetch() 方法。

在使用多态时,我们应该遵循一些原则和注意事项:

  1. 多态仅适用于类之间的继承关系或接口之间的实现关系。
  2. 在使用多态时,只能访问编译时类型中所声明的方法和属性,而不能直接访问运行时类型的特有方法和属性。
  3. 向上转型能够实现多态,而向下转型可能需要进行类型检查和类型转换,需要注意类型转换的时机和安全性。
  4. 多态在运行时动态绑定方法调用,使得程序能够根据实际对象的类型来决定调用哪个方法,这称为动态分派。
  5. 多态不适用于静态方法、私有方法和构造方法。

3.2 instanceof运算符

 instanceof来解决引用对象的类型,避免类型转换的安全性问题。

public class Animal {
    // 父类 Animal
}

public class Dog extends Animal {
    // 子类 Dog
}

public class Cat extends Animal {
    // 子类 Cat
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        if (animal instanceof Animal) {
            System.out.println("animal is an Animal");
        }
        if (animal instanceof Dog) {
            System.out.println("animal is a Dog");
        }
        if (animal instanceof Cat) {
            System.out.println("animal is a Cat");
        }
    }
}

上面的代码中,我们定义了一个 Animal 类,以及两个继承自 Animal 的子类 Dog 和 Cat。在 Main 类中,我们创建了一个 Dog 类型的对象,并将其赋值给一个 Animal 类型的变量 animal。接着,我们使用 instanceof 运算符检查 animal 是否是 Animal 类型的实例、Dog 类型的实例或 Cat 类型的实例,并打印相应的结果。

在上面的示例中,animal 是 Dog 类型的对象,因此 instanceof Animal 和 instanceof Dog 都返回 true,而 instanceof Cat 返回 false

4.常用关键字

4.1 static

static是Java中的一个关键词,它可以用于变量、方法和嵌套类。

下面是static关键词的使用及示例代码:

静态变量

public class Circle {
    private static double pi = 3.14159;
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double calculateArea() {
        return pi * radius * radius;
    }

    public static void main(String[] args) {
        Circle c1 = new Circle(5);
        Circle c2 = new Circle(3);

        System.out.println("Circle 1 area: " + c1.calculateArea());
        System.out.println("Circle 2 area: " + c2.calculateArea());
        System.out.println("Value of pi: " + Circle.pi);
    }
}

静态方法

public class MathUtils {
    public static int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        int result = MathUtils.add(3, 5);
        System.out.println("Result: " + result);
    }
}

静态嵌套类

public class OuterClass {
    private static int staticVar = 10;

    static class InnerStaticClass {
        private static int innerStaticVar = 20;

        public static void display() {
            System.out.println("Outer static var: " + staticVar);
            System.out.println("Inner static var: " + innerStaticVar);
        }
    }

    public static void main(String[] args) {
        OuterClass.InnerStaticClass.display();
    }
}

在使用 static 关键词时,需要注意以下事项:

  1. 静态成员变量和方法属于类,而不属于对象。因此,它们是共享的,所有的对象都可以访问和修改它们。

  2. 静态成员变量和方法可以使用类名直接调用,无需创建对象。但非静态成员变量和方法必须通过对象来调用。

  3. 静态方法只能访问静态成员变量和方法,不能访问非静态成员变量和方法。

  4. 静态成员变量和方法在内存中只存在一份。当一个对象对它们进行修改时,其他对象也会受到影响。

  5. 静态成员变量和方法的优点是可以提高程序的性能,因为它们只在类加载时初始化一次,而不需要在每次创建对象时初始化。

  6. 静态成员变量和方法不适合用于存储和处理对象的状态。因为它们是所有对象共享的,而对象的状态应该是独立的。

  7. 静态嵌套类与静态成员变量和方法类似,它与外部类相互独立,可以直接通过外部类名访问。静态嵌套类可以有自己的静态成员变量和方法。

4.2 final

下面是一个使用 `final` 关键字的示例代码:

public class Example {
    public static final int MAX_COUNT = 100;
    public final String name;

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

    public final void printInfo() {
        System.out.println("This is an example.");
    }

    // 错误示例:无法重写 final 方法
    // public void printInfo() {
    //     System.out.println("This is a different example.");
    // }

    public static void main(String[] args) {
        Example example = new Example("Example 1");
        example.printInfo();
        System.out.println("Name: " + example.name);
        System.out.println("Max Count: " + Example.MAX_COUNT);
    }
}

注意事项:

1. `final` 关键字可以用于变量,方法和类。它的意思是不可改变的或一次性的。

2. 对于变量,使用 `final` 关键字表示常量,即该值在初始化之后就不能再被改变。常量名通常使用大写字母表示,并且在声明时就需要进行初始化。

3. 对于方法,使用 `final` 关键字表示该方法不能被子类重写。在子类中定义相同的方法将会导致编译错误。

4. 对于类,使用 `final` 关键字表示该类不能被继承,即它是最终类。不能将一个继承类声明为 `final`。

5. `final` 关键字的使用可以提高性能,避免了被修改的风险,并且在代码中更加清晰明了。

6. 注意,`final` 变量的值只能被初始化一次,且无法被重新赋值。如果是引用类型的 `final` 变量,其引用指向的对象在初始化后仍然可以被修改。

7. `final` 方法虽然不能被重写,但仍然可以被重载。

5.接口与抽象类

Java中接口和抽象类的定义语法分别为interface与abstract关键字。

5.1抽象类

:在Java中被abstract关键字修饰的类称为抽象类,被abstract关键字修饰的方法称为抽象方法,抽象方法只有方法的声明,没有方法体。抽象类的特点:

a、抽象类不能被实例化只能被继承;

b、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法;

c、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public;

d、一个子类继承一个抽象类,则子类必须实现父类抽象方法,否则子类也必须定义为抽象类;

e、抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用。

5.2接口

Java中接口使用interface关键字修饰,特点为:

a、接口可以包含变量、方法;变量被隐士指定为public static final,方法被隐士指定为public abstract(JDK1.8之前);

b、接口支持多继承,即一个接口可以extends多个接口,间接的解决了Java中类的单继承问题;

c、一个类可以实现多个接口;

d、JDK1.8中对接口增加了新的特性:(1)、默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;(2)、静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。

如下例子所示:

public interface Person{
  public static final int a=10;
  //JDK1.8
    default void sayHello(){
        System.out.println("Hello World");
    }
    public void say();
}
public abstract class Person{
  public abstract void say();
  public void eat(){};
}

6.重载和重写

Java中的重载(Overloading)和重写(Overriding)是两种不同的概念。

6.1 重载

重载(Overloading)是指在同一个类中,允许存在多个同名的方法,但它们的参数列表必须不同(参数类型、个数或顺序)。重载方法可以在相同的类中提供不同的功能。可以根据不同的参数类型或个数来区分调用哪个重载方法。

下面是一个重载方法的示例代码:

class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }
}

public class Example {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        int result1 = calculator.add(5, 10); // 调用第一个add方法
        double result2 = calculator.add(2.5, 3.7); // 调用第二个add方法
        System.out.println(result1);
        System.out.println(result2);
    }
}

在上述示例中,`Calculator` 类中定义了两个名为 `add` 的方法,一个用于整数相加,另一个用于浮点数相加。通过重载方法,我们可以根据参数的类型来选择合适的方法。

6.2 重写

重写(Overriding)是指子类重新定义父类中已经定义的方法,方法名、参数列表和返回类型必须相同。重写方法用于扩展或修改父类的行为。在重写时,子类覆盖父类的方法实现,以实现子类特有的功能。

下面是一个重写方法的示例代码:

class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("狗发出汪汪声");
    }
}

public class Example {
    public static void main(String[] args) {
        Animal animal = new Animal();
        Dog dog = new Dog();
        
        animal.makeSound(); // 调用父类的方法
        dog.makeSound(); // 调用子类重写的方法
    }
}

在上述示例中,`Animal` 类中定义了 `makeSound` 方法,子类 `Dog` 重写了该方法。通过调用 `makeSound` 方法,可以看到子类的方法实现被调用。

需要注意的是:

1. 重载和重写是面向对象语言中的基本概念,用于提高代码的复用和灵活性。
2. 重载的方法是通过参数列表的不同来区分的,与返回类型和访问修饰符无关。
3. 重写的方法的方法名、参数列表和返回类型必须与父类的方法相同,并且访问修饰符不能更严格。
4. 在重写方法时,可以使用 `@Override` 注解来标识,这样可以确保方法的正确重写。
5. 在使用重载或重写时,需要注意方法签名的唯一性,方法的参数列表应该足够明确,以避免产生歧义。
6. 在调用重载或重写方法时,根据参数类型或对象的实际类型来确定具体调用哪个方法。
7. 在设计类时,要考虑到方法重载和方法重写的合理使用,以提高代码的可读性和可维护性。

7.内部类

内部类可分为以下几种:

  • 成员内部类
  • 静态内部类
  • 方法内部类
  • 匿名内部类

7.1成员内部类:


成员内部类是定义在外部类的成员位置(类的内部,方法的外部)的类。它可以访问外部类的所有成员,包括私有成员。成员内部类的示例代码和注意事项如下:

public class OuterClass {
    private int x = 10;

    class InnerClass {
        private int y = 5;

        public void display() {
            System.out.println("Outer x is " + x);
            System.out.println("Inner y is " + y);
        }
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();
        inner.display();
    }
}

注意事项:
1. 成员内部类需要通过外部类的实例来创建。语法为:`OuterClass.InnerClass inner = outerInstance.new InnerClass();`
2. 成员内部类可以访问外部类的所有成员,包括私有成员。
3. 成员内部类中不能定义静态成员(包括数据和方法),除非声明为`final static`常量。

7.2静态内部类:


静态内部类是定义在外部类的成员位置,但使用`static`修饰的内部类。它可以直接访问外部类的静态成员,但无法访问外部类的非静态成员。静态内部类的示例代码和注意事项如下:

public class OuterClass {
    private static int x = 10;

    static class InnerClass {
        private int y = 5;

        public void display() {
            System.out.println("Outer x is " + x);
            System.out.println("Inner y is " + y);
        }
    }

    public static void main(String[] args) {
        OuterClass.InnerClass inner = new OuterClass.InnerClass();
        inner.display();
    }
}

注意事项:
1. 静态内部类不依赖于外部类的实例,可以直接创建。
2. 静态内部类可以访问外部类的静态成员,但不能直接访问外部类的非静态成员。
3. 静态内部类中不能使用`this`关键字,因为它与外部类实例无关。

7.3方法内部类:


方法内部类是定义在方法内部的类,作用域仅限于所在的方法内部。它不能被方法外的代码访问,只能在方法内部使用。方法内部类的示例代码和注意事项如下:

public class OuterClass {
    private int x = 10;

    public void outerMethod() {
        class InnerClass {
            private int y = 5;

            public void display() {
                System.out.println("Outer x is " + x);
                System.out.println("Inner y is " + y);
            }
        }

        InnerClass inner = new InnerClass();
        inner.display();
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.outerMethod();
    }
}

注意事项:
1. 方法内部类只能在所在的方法内被访问。
2. 方法内部类可以访问外部类的成员,包括私有成员。
3. 方法内部类不能定义静态成员。

7.4匿名内部类:


匿名内部类是没有类名的内部类,它直接在创建对象的地方进行定义和实例化。通常用于创建只需要使用一次的类对象。匿名内部类的示例代码和注意事项如下:

public class OuterClass {
    public void display() {
        System.out.println("This is the outer class");
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();

        // 使用匿名内部类创建一个实现了Runnable接口的对象
        Runnable runnable = new Runnable() {
            public void run() {
                System.out.println("This is the inner class");
 }
}

匿名内部类在实现接口或继承类的同时,也可以覆盖父类或实现接口的方法,并且可以使用外部类的成员变量和方法,但是不能定义静态成员和方法。由于匿名内部类没有类名,因此无法在其他地方使用,且每次使用时都需要重新定义和实例化。
           

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值