Java构造器封装继承重写多态
一、构造器
在Java中,构造器(Constructor)是用于创建对象的一种特殊方法。构造器在类的实例化过程中被调用,用来初始化新对象的状态。构造器在面向对象编程中起着至关重要的作用,它确保每个对象在创建时都有一个有效的初始状态。本文将详细介绍Java构造器的概念、类型、用法及其注意事项。
一、什么是构造器
构造器是一种特殊的方法,它与类同名,没有返回类型(甚至不写void),用于初始化对象。构造器在对象创建时由Java虚拟机(JVM)自动调用,确保对象的初始状态。
1、构造器的基本语法
public class ClassName {// 构造器public ClassName() {// 初始化代码}
}
二、构造器的类型
1、默认构造器
如果类没有显式定义任何构造器,Java编译器会自动提供一个无参数的默认构造器。这个默认构造器不做任何特殊操作,只是简单地创建一个对象。
public class Student {// 编译器会自动提供一个无参数的默认构造器
}
public class Main {public static void main(String[] args) {Student student = new Student(); // 调用默认构造器}
}
2、无参数构造器
无参数构造器是用户显式定义的不带参数的构造器,用于初始化对象。
public class Student {public Student() {System.out.println("无参数构造器被调用");}
}
public class Main {public static void main(String[] args) {Student student = new Student(); // 调用无参数构造器}
}
3、 带参数构造器
带参数构造器允许在创建对象时传递参数,用于初始化对象的属性。
public class Student {String name;int age;public Student(String name, int age) {this.name = name;this.age = age;}
}
public class Main {public static void main(String[] args) {Student student = new Student("Alice", 20); // 调用带参数的构造器System.out.println("Name: " + student.name + ", Age: " + student.age);}
}
三、构造器的重载
构造器可以被重载,这意味着在一个类中可以定义多个构造器,它们的参数列表(参数类型、个数或顺序)不同。构造器重载使得对象初始化更加灵活。
public class Student {String name;int age;// 无参数构造器public Student() {this.name = "Unknown";this.age = 0;}// 带一个参数的构造器public Student(String name) {this.name = name;this.age = 0;}// 带两个参数的构造器public Student(String name, int age) {this.name = name;this.age = age;}
}
public class Main {public static void main(String[] args) {Student student1 = new Student();Student student2 = new Student("Bob");Student student3 = new Student("Charlie", 22);System.out.println("student1 - Name: " + student1.name + ", Age: " + student1.age);System.out.println("student2 - Name: " + student2.name + ", Age: " + student2.age);System.out.println("student3 - Name: " + student3.name + ", Age: " + student3.age);}
}
四、构造器的调用
1、使用this调用重载的构造器
在一个构造器中,可以使用this关键字调用同一类中的另一个构造器。这种调用必须是构造器中的第一条语句。
public class Student {String name;int age;public Student() {this("Unknown", 0); // 调用带参数的构造器}public Student(String name) {this(name, 0); // 调用带两个参数的构造器}public Student(String name, int age) {this.name = name;this.age = age;}
}
public class Main {public static void main(String[] args) {Student student1 = new Student();Student student2 = new Student("Bob");Student student3 = new Student("Charlie", 22);System.out.println("student1 - Name: " + student1.name + ", Age: " + student1.age);System.out.println("student2 - Name: " + student2.name + ", Age: " + student2.age);System.out.println("student3 - Name: " + student3.name + ", Age: " + student3.age);}
}
2、调用父类的构造器
在子类的构造器中,可以使用super关键字调用父类的构造器。这种调用必须是子类构造器中的第一条语句。
public class Person {String name;public Person(String name) {this.name = name;}
}
public class Student extends Person {int age;public Student(String name, int age) {super(name); // 调用父类的构造器this.age = age;}
}
public class Main {public static void main(String[] args) {Student student = new Student("Alice", 20);System.out.println("Name: " + student.name + ", Age: " + student.age);}
}
五、构造器的注意事项
1、构造器没有返回类型:构造器不能有返回类型(甚至不能写void),否则它会被认为是一个普通方法。
2、构造器的名称必须与类名相同:构造器的名称必须与类名完全一致,包括大小写。
3、不能继承构造器:构造器不能被继承,但子类可以调用父类的构造器。
4、构造器可以抛出异常:构造器可以使用throws关键字声明抛出异常,调用构造器时需要处理这些异常。
二、封装
一、Java 封装是什么
在 Java 中,封装是一种基本的面向对象编程概念。简单来说,它就像是把数据和对数据的操作包装在一起,形成一个独立的单元。例如,一个汽车类,汽车的各种属性(如颜色、型号、速度等)以及对这些属性进行操作的方法(如加速、减速、停车等),都被封装在汽车这个类中。这样,外界就不能随意访问和修改类内部的数据,而只能通过类提供的方法来进行操作。
二、Java 封装的作用
1、数据隐藏:
通过封装,将类的内部数据隐藏起来,避免外部直接访问和修改。这就像你的私人日记,你不会随意让别人翻阅和修改,只有你自己可以控制对它的操作。比如一个用户类,用户的密码字段是非常敏感的,通过封装,将密码字段设置为私有,外部就无法直接获取和修改密码,保证了数据的安全性。
2、提高代码的可维护性:
当类的内部实现发生变化时,只要对外提供的接口不变,就不会影响到其他使用这个类的代码。比如一个计算面积的类,最初使用一种算法计算面积,后来因为性能优化更换了算法,但是只要提供给外部调用的计算面积的方法名和参数不变,其他依赖这个类的代码就不需要修改,降低了代码维护的难度。
3、增强代码的复用性:
封装好的类可以被多个地方重复使用。例如,一个工具类封装了各种常用的字符串操作方法,在不同的项目模块中都可以引入这个工具类来使用这些方法,提高了开发效率。
三、Java 封装的实现方式
访问修饰符:在 Java 中,主要通过访问修饰符来实现封装。常见的访问修饰符有 private、default(默认,不写修饰符就是 default)、protected 和 public。
1、private:被 private 修饰的成员(属性或方法)只能在本类中访问。例如:
public class Person {
private String name;
private int age;
// 私有方法,只能在本类中调用
private void privateMethod() {
System.out.println("这是一个私有方法");
}
}
2、default:默认访问修饰符,被它修饰的成员可以在同一个包内访问。如果一个类没有指定包名,那么它属于默认包,同一个源文件中的类都在默认包内。例如:
package com.example;
public class Animal {
// 默认访问修饰符,同一个包内可以访问
int legs;
// 默认访问修饰符的方法,同一个包内可以调用
void run() {
System.out.println("动物在跑");
}
}
3、protected:被 protected 修饰的成员可以在同一个包内以及不同包的子类中访问。例如:
package com.example;
public class Parent {
protected String protectedField;
protected void protectedMethod() {
System.out.println("这是一个受保护的方法");
}
}
package com.other;
import com.example.Parent;
public class Child extends Parent {
public void useProtected() {
protectedField = "测试";
protectedMethod();
}
}
4、public:被 public 修饰的成员可以在任何地方访问。例如:
public class PublicClass {
public String publicField;
public void publicMethod() {
System.out.println("这是一个公共方法");
}
}
四、Java 封装的访问与设置
1、Getter 和 Setter 方法:
对于私有属性,通常会提供 public 的 Getter 和 Setter 方法来访问和修改这些属性。
Getter 方法用于获取属性的值,Setter 方法用于设置属性的值。例如:
public class Student {
private String name;
private int age; // Getter方法
public String getName() {
return name;
}// Setter方法
public void setName(String name) {
this.name = name;
}// Getter方法
public int getAge() {
return age;
}// Setter方法
public void setAge(int age) {
if (age > 0 && age < 120) {
this.age = age;
} else {
System.out.println("年龄不合法");
}
}
}
在上述代码中,通过 Getter 和 Setter 方法,可以对私有属性进行安全的访问和修改,在 Setter 方法中还可以添加一些逻辑判断,保证设置的数据是合法的。
三、继承
1、继承的基本介绍
当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。
继承的基本思想是,可以基于已有的类创建新的类。继承已存在的类就是复用(继承)这些类的方法,而且可以增加一些新的方法和字段(成员变量)。继承是面向对象的三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。子类和父类之间,从意义上讲应该具有"is a"的关系。
2、继承的格式:
格式: public class 子类名 extends 父类名{}
例如: public class Zi extends Fu {}
Fu: 是父parent类,也被称为基base类、超super类
Zi: 是子child类,也被称为派生sub类
继承是指在原有类的基础上,进行功能扩展,创建新的类型。
3、继承的优缺点
继承好处:
实现了数据和方法的共享
提高了代码的复用性(多个类相同的成员可以放到同一个类中)
提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
提高了代码的可扩展性
继承弊端:
继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟看变化,削弱了子类的独立性
4、继承类型
1)单一继承
单继承很容易理解。当一个类只扩展另一个类时,我们称之为单个继承。
下面的流程图显示B类只扩展了一个A类。这里A是B 的父类,B 是A 的子类。
Class A
{public void methodA(){System.out.println("Base class method");}
}Class B extends A
{public void methodB(){System.out.println("Child class method");}public static void main(String args[]){B obj = new B();obj.methodA(); //calling super class methodobj.methodB(); //calling local method}
}
2)多级继承
多级继承是指OO技术中的一种机制,其中可以从派生类继承,从而使该派生类成为新类的基类。
正如您在下面的流程图中看到的,C是B的子类或子类,B是A的子类。
Class X
{public void methodX(){System.out.println("Class X method");}
}
Class Y extends X
{public void methodY(){System.out.println("class Y method");}
}
Class Z extends Y
{public void methodZ(){System.out.println("class Z method");}public static void main(String args[]){Z obj = new Z();obj.methodX(); //calling grand parent class methodobj.methodY(); //calling parent class methodobj.methodZ(); //calling local method}
}
3)分层继承
在这种类型的继承中,一个类由许多子类继承。
在下面的示例类B中,C和D 继承了相同的类A。
A是B,C和D 的父类(或基类)。
四、super
super 关键字的用法和 this 关键字的用法相似
this:代表本类对象的引用(this关键字指向调用该方法的对象一般我们是在当前类中使用this关键字所以我们常说this代表本类对象的引用)
super:代表父类存储空间的标识(可以理解为父类对象引用)
例如:定义一个父类Fu
public class Fu {public int age = 10;}
定义一个子类Zi
public class Zi extends Fu {public int age = 20;public void show() {int age = 30;System.out.println(age); // 30// 访问本类中的成员变量ageSystem.out.println(this.age);// 访问Fu类中的成员变量ageSystem.out.println(super.age);}
}
测试:Test
public class Test {public static void main(String[] args) {Zi z = new Zi();z.show();}
}
结果: