getter和setter
在面向对象编程中,我们通常将类的成员变量(属性)声明为 private,以隐藏内部实现细节,防止外部直接访问和修改。但有时外部需要读取或修改这些属性的值,此时就需要提供公开的 getter(获取)和 setter(设置)方法。
核心目的:实现封装 ------ 将数据和行为包装在类内部,对外提供受控的访问接口。
成员变量一般使用private来声明,保护成员变量不被胡乱赋值
好处:
1.控制读写权限(只读:只有 getter,没有 setter)
2.校验数据合法性(在 setter 中检查边界)
3.统一修改接口(便于日后扩展,如增加日志、触发事件)
4.隐藏内部表示(可以改变内部存储方式而不影响外部代码)
setter:主要是给成员变量赋值,做一定的保护
getter:从成员变量中获取数据
命名规范:
|------------------------|------------------------------|-------------------------------|
| 类型 | 方法命名格式 | 示例(属性 name) |
| getter | public 返回值类型 getXxx() | public String getName() |
| setter | public void setXxx(参数类型 参数名) | public void setName(String n) |
| boolean 类型的 getter(可选) | public boolean isXxx() | public boolean isMarried() |
快捷键:
空白位置->右键->generate->getter and setter->全选->OK
java
public class Student {
private String name; // 私有属性
private int age;
private boolean married;
// getter
public String getName() {
return name;
}
// setter
public void setName(String name) {
this.name = name; // this 区分成员变量和参数
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0 && age <= 150) { // 数据校验
this.age = age;
} else {
System.out.println("年龄不合法!");
}
}
// boolean 类型推荐使用 isXxx
public boolean isMarried() {
return married;
}
public void setMarried(boolean married) {
this.married = married;
}
}
使用示例:
java
Student s = new Student();
s.setName("张三");
s.setAge(20);
System.out.println(s.getName() + " 年龄:" + s.getAge());
与封装的关系图解
┌─────────────────────────────────┐
│ Student │
├─────────────────────────────────┤
│ - name : String │ ← private 属性(隐藏)
│ - age : int │
├─────────────────────────────────┤
│ + getName() : String │ ← public getter
│ + setName(String) : void │ ← public setter(带校验)
│ + getAge() : int │
│ + setAge(int) : void │
└─────────────────────────────────┘
↑
│ 通过公开方法访问
│
外部代码(Client)
继承
继承:子类可以自动拥有父类除了私有内容外的其他所有内容
当出现x是一种y的时候,x就可以继承y
写法:public class 类 extends 父类 {}
Java 不支持多继承,一个子类只能有一个直接父类
作用:
简化代码的开发
子类对父类进行了扩展
java
// 父类
public class Animal {
String name;
int age;
public void eat() {
System.out.println(name + "正在吃东西");
}
}
// 子类 Dog 继承 Animal
public class Dog extends Animal {
// 自动拥有了 name、age 属性和 eat() 方法
public void bark() {
System.out.println(name + "汪汪叫");
}
}
// 使用
Dog dog = new Dog();
dog.name = "旺财";
dog.age = 2;
dog.eat(); // 旺财正在吃东西
dog.bark(); // 旺财汪汪叫
继承中的成员访问规则
|---------|-----------------------------------------------|
| 访问 | 子类中能否直接访问(不通过父类引用) |
| public | ✅ 可以 |
| default | 仅当子类与父类在同一个包时才可以 |
| private | ❌ 不可以(但可以通过父类提供的 public/protected 方法间接访问) |
子类只继承父类中非 private 的成员变量和方法。构造方法不能被继承,但可以在子类中调用。
super()关键字
super:表示父类中的内容;this:表示自己类中的内容(用super和this来区分父类和子类中重名的内容)
java
public class Hero {
String name = "英雄";
}
public class SunWuKong extends Hero{
String name = "孙大圣";
public void chi() {
//先找自己类,再找父类
System.out.println(this.name + "在吃桃子");
//如果此时想看到父类中的内容
System.out.println(super.name + "在吃桃子");
}
public static void main(String[] args) {
SunWuKong s = new SunWuKong();
s.chi();
}
}

java
public class Hero {
String name = "英雄";
public Hero() {
System.out.println("我是父类的构造方法");
}
}
public class SunWuKong extends Hero{
String name = "孙大圣";
public SunWuKong() {
//程序是先执行这个子类构造,但是在这个位置会隐含着super(); 所以最后会先输出父类的构造
//还原程序:在子类构造方法的第一行,默认调用父类的构造方法
System.out.println("我是子类的构造方法");
}
public void chi() {
System.out.println(this.name + "在吃桃子");
System.out.println(super.name + "在吃桃子");
}
public static void main(String[] args) {
SunWuKong s = new SunWuKong();
s.chi();
}
}
/*输出:
我是父类的构造方法
我是子类的构造方法
孙大圣在吃桃子
英雄在吃桃子*/
创建对象的过程:先创建父类的对象,然后创建子类的对象
super 是 Java 中用于引用父类对象的关键字。它主要用于三个方面:
调用父类的构造方法(super() 或 super(参数))(必须写在子类构造方法的第一行,如果父类的构造是无参数的,可以不写,如果父类没有无参数的构造,必须要写super)
访问父类的成员变量(super.变量名)
调用父类的成员方法(super.方法名())
调用父类的构造方法
子类构造方法必须调用父类的构造方法(隐式或显式)。如果父类没有无参构造,子类必须在第一行显式调用 super(参数)。
java
super(); // 调用父类无参构造
super(参数列表); // 调用父类有参构造
规则
1.super() 必须写在子类构造方法的第一行
2.super() 和 this() 不能同时出现(都要求在第一行)
3.如果子类构造方法没有写任何 super(),编译器会自动添加 super()
java
class Person {
String name;
Person(String name) {
this.name = name;
}
}
class Student extends Person {
int score;
Student(String name, int score) {
super(name); // 必须显式调用父类有参构造
this.score = score;
}
}
访问父类的成员变量
当子类定义了与父类同名的变量时,使用 super 可以区分并访问父类的变量
java
class Father {
String name = "父亲";
}
class Son extends Father {
String name = "儿子";
void print() {
System.out.println(name); // 儿子
System.out.println(super.name); // 父亲
}
}
调用父类的成员方法
当子类重写了父类的方法,使用 super 可以调用父类中被覆盖的版本
java
class Animal {
void sound() {
System.out.println("动物发出声音");
}
}
class Cat extends Animal {
@Override
void sound() {
super.sound(); // 调用父类的 sound()
System.out.println("喵喵喵");
}
}
super 与 this 的区别
|-------|------|----------------------|
| 关键字 | 指向 | 用途 |
| this | 当前对象 | 访问当前对象的成员、调用本类其他构造方法 |
| super | 父类对象 | 访问父类的成员、调用父类构造方法 |
注意:
在静态方法中不能使用 this 或 super(因为不存在当前对象/父类对象)
super 并不是一个引用变量(不能赋值),它只是一个指示编译器调用父类成员的关键字
常见误区与注意事项
1.父类没有无参构造时,子类必须显式调用有参构造
java
class Parent {
Parent(int x) {}
}
class Child extends Parent {
Child() {
super(10); // 必须
}
}
2.super()和 this()不能构造
因为两者都要求位于构造方法的第一行,只能选择其一。
3.不能通过 super 访问父类的 private 成员
private 成员在子类中不可见,即使是 super 也无法访问。
4.super 调用方法时,仍然遵循动态绑定
若父类方法被子类重写,super.方法() 调用的是父类版本,而不是子类版本。