一.访问控制
只针对类,对象,属性。
private->default->protected->public(控制级别由小到大)
二.面向对象三大特性
1.封装
好处:可以对类中的成员变量的访问做出一些限定,不允许外界随意访问。但是可以通过该类提供的方法实现对内部信息的操作访问。
如何实现封装?
1.将类中的属性私有化(使用private关键字修饰)
2.若想访问私有属性,通过setter和getter方法设置和获取属性值(系统提供)
public class Person {
private String name; //属性私有化
private int age;
public String getName() { //设置setter和getter方法
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age > 0) {
this.age = age;
} else {
System.out.println("年龄必须大于0");
}
}
}
2.继承
特点:表示事务之间的所属关系,使用extends关键字表示。
class ParentClass {
// 父类的属性和方法
}
class ChildClass extends ParentClass {
// 子类的属性和方法
}
注意:
1.子类不仅可以继承父类的属性和方法,也可以定义自己的属性和方法。
2.类只支持单继承,不允许多继承
3.多个类可以继承一个父类
4.子类不能直接访问和调用父类的私有成员,但是可以调用父类的非私有方法
3.多态
特点:指同一操作作用于不同对象时产生不同的行为(方法)
Java中多态分为编译时多态(方法重载)和运行时多态(方法重写与对象向上转型)。
编译时多态(静态多态)
通过方法重载(Overloading)实现,即在同一个类中定义多个同名方法,但参数列表不同(类型、数量或顺序)。编译器在编译阶段根据参数类型决定调用哪个方法。
// 示例:方法重载
class Calculator {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
}
运行时多态(动态多态)
通过方法重写(Overriding)和继承实现,子类重写父类的方法后,程序运行时根据对象的实际类型调用对应方法。需满足以下条件:
继承关系:子类继承父类。
方法重写:子类重写父类的方法(方法名、参数列表、返回类型相同)。
向上转型:父类引用指向子类对象(如 Parent obj = new Child()
)。
// 示例:方法重写
class Animal {
void sound() { System.out.println("Animal makes sound"); }
}
class Dog extends Animal {
@Override
void sound() { System.out.println("Dog barks"); }
}
public class Main {
public static void main(String[] args) {
Animal obj = new Dog(); // 向上转型
obj.sound(); // 输出 "Dog barks"
}
}
注意事项
成员变量无多态:多态仅适用于方法,成员变量访问取决于引用类型。
静态方法无多态:静态方法属于类,调用时看引用类型而非实际对象。
私有方法不可重写:私有方法无法被继承,故不能多态。
// 示例:成员变量无多态
class Parent { int val = 1; }
class Child extends Parent { int val = 2; }
Parent obj = new Child();
System.out.println(obj.val); // 输出 1(看引用类型)
4.方法的重写
特点:指子类重新定义父类中已存在的方法。重写的方法必须与父类方法具有相同的名称、参数列表和返回类型。通过方法重写,子类可以根据自身需求改变父类方法的实现。
重写规则:
- 子类方法的名称、参数列表和返回类型必须与父类方法完全一致。
- 子类方法的访问权限不能低于父类方法的访问权限。
- 父类方法若为
final
或static
,则不能被重写。 - 子类方法抛出的异常类型不能比父类方法抛出的异常类型更宽。
class Animal { public void makeSound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override public void makeSound() { System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal animal = new Dog(); animal.makeSound(); // Output: Dog barks } }
方法重写与重载的区别
方法重写与方法重载(Overloading)是两个不同的概念:
- 重写发生在父子类之间,要求方法名完全相同
- 重载发生在同一类中,要求方法名相同且参数列表不同
- 使用
@Override
注解可以帮助编译器检查方法重写的正确性。
5.super关键字
super特点:用于在子类中调用父类的成员(属性或方法)。
super与this的区别
- super指向父类对象引用,this指向当前对象引用
- super用于访问父类成员,this用于访问当前类成员
- super()调用父类构造方法,this()调用本类其他构造方法
注意事项:
1.构造方法中super()或this()必须放在第一行
2.普通方法中super可以出现在任意位置
3.若父类没有无参构造且未显式调用super,编译器将报错
6.this关键字
特点:主要用于区分实例变量和局部变量,尤其是在变量名相同时。this
可以帮助明确访问当前对象的成员变量或方法。
1.使用 this 区分类成员与局部变量
当方法的参数名与类的成员变量名相同时,可以使用 this
来区分成员变量和局部变量。
public class Example {
private int value;
public void setValue(int value) {
this.value = value; // 使用 this 指向成员变量
}
}
2.使用 this 调用当前类的方法
this
可以用于调用当前类的其他方法,通常用于在方法中调用另一个方法。
public class Example {
public void methodA() {
System.out.println("Method A");
}
public void methodB() {
this.methodA(); // 使用 this 调用方法
}
}
3.使用 this 调用当前类的构造函数
this
可用于在一个构造函数中调用另一个构造函数,但必须作为构造函数的第一条语句。
public class Example {
private int x;
private int y;
public Example() {
this(0, 0); // 调用带参数的构造函数
}
public Example(int x, int y) {
this.x = x;
this.y = y;
}
}
4.this 作为参数传递
this
可以作为参数传递给方法或构造函数,常用于将当前对象传递给其他方法。
public class Example {
public void print() {
display(this); // 传递当前对象
}
public void display(Example obj) {
System.out.println("Displaying object");
}
}
5.this 在匿名类和内部类中的使用
在匿名类或内部类中,this
指向的是当前匿名类或内部类的实例。如果需要访问外部类的实例,可以使用 OuterClassName.this
。
public class Outer {
private int value = 10;
public class Inner {
private int value = 20;
public void print() {
System.out.println(this.value); // 输出 20
System.out.println(Outer.this.value); // 输出 10
}
}
}
this 的注意事项
this
不能在静态方法或静态代码块中使用,因为静态成员属于类而非实例。使用 this
会导致编译错误。
public class Example {
private static int count;
public static void printCount() {
// System.out.println(this.count); // 编译错误
}
}
7.构造方法
特点:用于创建对象时初始化对象的状态。构造方法的名称必须与类名完全相同,且没有返回类型(包括void
)。
1.默认构造方法
如果一个类没有显式定义构造方法,Java编译器会自动提供一个无参数的默认构造方法。默认构造方法会将成员变量初始化为默认值(如int
为0
,对象为null
)。
public class Person {
private String name;
// 默认构造方法(隐式存在)
// public Person() {}
}
2.自定义构造方法
可以定义带参数的构造方法,用于在对象创建时直接初始化成员变量。
public class Person {
private String name;
private int age;
// 自定义构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
3.构造方法的重载
一个类可以有多个构造方法,只要它们的参数列表不同(方法重载)。
public class Person {
private String name;
private int age;
// 无参构造方法
public Person() {
this.name = "Unknown";
this.age = 0;
}
// 带参构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
4.构造方法与this
关键字
在构造方法中,this
关键字可用于调用同一类的其他构造方法(必须放在第一行)。
public class Person {
private String name;
private int age;
public Person() {
this("Unknown", 0); // 调用带参构造方法
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
5.构造方法的访问修饰符
构造方法可以设置为public
、protected
、private
或默认
public class Singleton {
private static Singleton instance;
// 私有构造方法
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
6.构造方法与继承
子类构造方法默认调用父类的无参构造方法(通过super()
)。如果父类没有无参构造方法,子类必须显式调用父类的带参构造方法。
public class Animal {
private String type;
public Animal(String type) {
this.type = type;
}
}
public class Dog extends Animal {
public Dog() {
super("Dog"); // 必须调用父类带参构造方法
}
}
8.final关键字
特点:用于声明不可变的实体。通常用于变量、方法或类,表示一旦定义后不可修改、重写或继承。
1.final在变量中的使用
当用于变量时,final
表示该变量只能被赋值一次,后续不可更改。
final int MAX_VALUE = 100;
// MAX_VALUE = 200; // 编译错误,不可重新赋值
- 对于基本类型,
final
使值不可变。 - 对于对象引用,
final
使引用不可变(即不能指向其他对象),但对象内部状态可能仍可修改。2.final在方法中的使用
当用于方法时,
final
表示该方法不能被子类重写(覆盖)。class Parent { final void display() { System.out.println("不可重写的方法"); } } class Child extends Parent { // void display() { } // 编译错误,无法重写final方法 }
3.final在类中的使用
当用于类时,
final
表示该类不能被继承。final class ImmutableClass { } // class SubClass extends ImmutableClass { } // 编译错误,不可继承final类
9.抽象类
特点:是一种不能被实例化的类,通常用作其他类的基类。它包含抽象方法(没有具体实现的方法)和具体方法(有实现的方法)。抽象类的主要目的是为子类提供通用的接口和部分实现,强制子类完成特定的功能。
抽象类适合用于定义一组相关类的共同行为,同时允许某些行为由子类具体实现。
抽象类定义规则:
1.包含抽象方法的类必须是抽象类
2.抽象类和抽象方法都需要使用abstract关键字声明
3.抽象方法只需要生命不需要实现
4.如果一个类继承了抽象类,那该子类必须实现抽象类中的全部抽象方法
抽象类与接口的区别
抽象类可以包含方法的实现,而接口只能包含抽象方法(Java 8之前)。一个类可以实现多个接口,但只能继承一个抽象类。抽象类更适合用于共享代码或状态,而接口更适合定义行为契约。
抽象类可以有构造方法,接口不能有构造方法。抽象类的成员变量可以是任何访问修饰符,接口的成员变量默认是public static final
。抽象类的抽象方法可以是public
、protected
,接口的方法只能是public
。
// 抽象类定义
abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
// 抽象方法
public abstract void makeSound();
// 具体方法
public void eat() {
System.out.println(name + " is eating.");
}
}
// 子类实现
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
// 使用
public class Main {
public static void main(String[] args) {
Animal dog = new Dog("Buddy");
dog.makeSound();
dog.eat();
}
}
10.接口
特点:用于定义一组方法而不提供实现,可以实现多继承。接口通过interface
关键字定义,类可以通过implements
关键字实现接口。
public interface Vehicle {
void start();
void stop();
String getType();
}
1.实现接口
类实现接口时必须提供接口中所有方法的实现,否则必须声明为抽象类。
public class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car started");
}
@Override
public void stop() {
System.out.println("Car stopped");
}
@Override
public String getType() {
return "Automobile";
}
}
2.接口的默认方法
Java 8开始允许在接口中定义默认方法,提供方法的默认实现。实现类可以选择重写默认方法或直接使用默认实现。
public interface Vehicle {
void start();
void stop();
default String getType() {
return "Generic Vehicle";
}
}
3.接口的静态方法
Java 8也允许在接口中定义静态方法,这些方法可以直接通过接口名调用。
public interface Vehicle {
static void displayVersion() {
System.out.println("Vehicle Interface v1.0");
}
}
// 调用方式
Vehicle.displayVersion();
4.接口的多重继承
Java不支持类的多重继承,但一个类可以实现多个接口,从而获得多重继承的效果。
public interface Electric {
void charge();
}
public class ElectricCar implements Vehicle, Electric {
// 必须实现所有接口方法
}