Java是一种面向对象的编程语言,类是Java中最基本的编程单元。一个类可以包含变量、方法和构造函数等。类的定义需要使用关键字class,例如:
```
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void sayHello() {
System.out.println("Hello, my name is " + name + ", and I am " + age + " years old.");
}
// getters and setters for name and age
}
```
上面的代码定义了一个名为Person的类,包含了私有变量name和age,以及构造函数和公有方法sayHello。构造函数用来初始化对象的状态,而sayHello方法用来输出对象的信息。除此之外,还可以为类定义公有和私有方法,访问控制修饰符包括public、private、protected和默认(没有修饰符)等。
Java类
1. 类的定义
1.1 类的基本概念
1.1.1 类的基本概念
类是Java中最基本的代码单元,它是一种用户自定义的数据类型,用于封装数据和方法。类可以看作是一个模板或蓝图,描述了一类对象的属性和行为。在Java中,类的定义通常包括类名、类的成员变量、类的方法等。其中,类名是唯一的,并且必须与文件名相同。类的成员变量是描述类的属性的变量,可以是基本数据类型或其他类的对象。类的方法是描述类的行为的函数,可以访问类的成员变量和其他类的对象。我们可以通过创建对象来实例化一个类,即在内存中分配空间来存储该类的实例,并调用其方法来操作实例的属性和行为。例如,下面是一个简单的Java类定义示例:
public class Person { // 成员变量 private String name; private int age; // 构造方法 public Person(String name, int age) { this.name = name; this.age = age; } // 成员方法 public void sayHello() { System.out.println("Hello, my name is " + name + ", I'm " + age + " years old."); } }
在上面的示例中,我们定义了一个名为Person的类,它有两个成员变量name和age,一个构造方法Person(String name, int age),和一个成员方法sayHello()。我们可以通过以下代码创建一个Person对象,并调用其sayHello()方法:
Person person = new Person("Tom", 18); person.sayHello();
输出结果为:
Hello, my name is Tom, I'm 18 years old.
通过上面的示例,我们可以看到类的定义是Java程序的基础,它提供了一种封装和抽象的方式来组织代码,使得程序更加清晰和易于维护。
1.2 类的语法结构
1.2.1 类的成员变量
类的成员变量定义在类的花括号内,与方法定义平级。成员变量可以是任何数据类型,包括Java中的基本数据类型和自定义数据类型。定义成员变量时需要指定访问权限修饰符,常用的有public、private和protected。访问权限修饰符的作用是控制成员变量的访问范围,保证数据的安全性和封装性。
1.2.2 类的方法
类的方法定义在类的花括号内,与成员变量定义平级。方法可以是任何数据类型,包括Java中的基本数据类型和自定义数据类型。定义方法时需要指定访问权限修饰符和方法返回值类型。访问权限修饰符的作用与成员变量相同,方法返回值类型指定方法返回的数据类型,如果方法不返回任何数据,则返回值类型为void。方法可以有参数列表,参数列表中指定方法的输入参数,参数列表可以为空。
1.2.3 类的构造方法
类的构造方法是一种特殊的方法,用于创建类的对象。构造方法的名称必须与类名相同,没有返回值类型,可以有参数列表。在创建类的对象时,会自动调用构造方法来完成对象的初始化。如果没有定义构造方法,则系统会自动生成一个默认的构造方法,该方法没有参数,也没有任何操作。
1.2.4 类的静态成员
类的静态成员指的是类的成员变量和方法,它们被static关键字修饰。静态成员可以直接通过类名来访问,不需要创建类的对象。静态成员在类加载时就已经被分配了内存空间,可以在任何时候被访问和调用。静态成员的作用是在整个程序中共享数据和方法,节省内存空间和提高程序的执行效率。
1.3 类的构造方法
1.3.1 无参构造方法
无参构造方法是指不带参数的构造方法,它的作用是在创建对象时初始化对象的属性,比如设置默认值等。在Java中,如果一个类没有定义任何构造方法,那么编译器会自动为该类生成一个无参构造方法。
以下是一个示例代码:
public class Person { private String name; private int age; // 无参构造方法 public Person() { this.name = "Unknown"; this.age = 0; } // 其他方法 // ... }
在上面的示例代码中,我们定义了一个名为Person的类,并且定义了一个无参构造方法。在该方法中,我们设置了name属性的默认值为"Unknown",age属性的默认值为0。
1.3.2 带参构造方法
带参构造方法是指带有参数的构造方法,它的作用是在创建对象时初始化对象的属性,并且可以根据传入的参数设置属性的值。在Java中,我们可以定义多个带参构造方法,每个构造方法可以接收不同类型和数量的参数。
以下是一个示例代码:
public class Person { private String name; private int age; // 带参构造方法 public Person(String name, int age) { this.name = name; this.age = age; } // 其他方法 // ... }
在上面的示例代码中,我们定义了一个名为Person的类,并且定义了一个带参构造方法。在该方法中,我们根据传入的参数设置了name属性和age属性的值。
使用带参构造方法创建对象的示例代码:
Person person = new Person("Tom", 20);
在上面的示例代码中,我们使用带参构造方法创建了一个Person对象,并且传入了参数"name"和"age",这样就可以在创建对象时初始化对象的属性。
2. 类的继承
2.1 继承的概念
3.1.1 继承的概念
继承是面向对象编程中的一种重要机制,它允许新的类从已有的类中继承属性和方法。在Java中,一个类可以通过关键字“extends”来继承另一个类的属性和方法。被继承的类称为父类或超类,继承的类称为子类或派生类。子类可以使用父类的公共方法和属性,同时还可以添加自己的方法和属性。继承是实现代码重用和提高代码可读性的重要手段。下面是一个简单的示例:
public class Animal { private String name; private int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat() { System.out.println(name + " is eating."); } public void sleep() { System.out.println(name + " is sleeping."); } } public class Dog extends Animal { public Dog(String name, int age) { super(name, age); } public void bark() { System.out.println("Woof! Woof!"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog("Tommy", 3); dog.eat(); // 继承自Animal类 dog.sleep(); // 继承自Animal类 dog.bark(); // 自己的方法 } }
在上面的示例中,Dog类继承了Animal类的属性和方法,同时也添加了自己的方法bark。在Main类中,我们可以创建一个Dog对象并调用它的方法,包括从Animal类继承来的方法和Dog类自己的方法。这个示例展示了继承的基本概念和用法。
2.2 继承的语法结构
2.2.1 继承关键字
继承是面向对象编程中的重要概念,Java中使用关键字extends
来实现类的继承。子类继承父类后,可以直接使用父类中的属性和方法,也可以通过重写方法来实现自己的特定功能。下面是一个示例:
public class Animal { private String name; public Animal(String name) { this.name = name; } public void eat() { System.out.println(name + " is eating."); } } public class Dog extends Animal { public Dog(String name) { super(name); } @Override public void eat() { System.out.println("Dog " + super.name + " is eating bones."); } public void bark() { System.out.println("Dog " + super.name + " is barking."); } } public class Main { public static void main(String[] args) { Animal animal = new Animal("Tom"); Dog dog = new Dog("Jerry"); animal.eat(); // 输出:Tom is eating. dog.eat(); // 输出:Dog Jerry is eating bones. dog.bark(); // 输出:Dog Jerry is barking. } }
在上面的示例中,Dog
类继承了Animal
类,通过重写eat()
方法实现了自己的特定功能,同时新增了一个bark()
方法。在Main
类中,我们创建了一个Animal
对象和一个Dog
对象,分别调用它们的方法,可以看到子类Dog
继承了父类Animal
的属性和方法,并且通过重写方法实现了自己的特定功能。
2.3 继承的方法重写
2.3.1 什么是方法重写
方法重写是指子类重新定义父类中已经定义的方法,但保持方法名、参数列表和返回类型与父类方法相同。在程序运行时,当调用子类对象的该方法时,会优先调用子类中重写的方法,而不是父类中的方法。
2.3.2 方法重写的实现
子类重写方法时,需要注意以下几点: - 方法名、参数列表和返回类型必须与父类中被重写的方法一致。 - 访问权限不能低于父类中被重写的方法的访问权限。 - 子类方法抛出的异常类型不能超出父类方法抛出的异常类型范围。 - 子类方法不能使用父类方法中声明为final的变量或方法。
下面是一个示例代码,演示了如何在子类中重写父类的方法:
public class Animal { public void move() { System.out.println("动物在移动"); } } public class Dog extends Animal { public void move() { System.out.println("狗在奔跑"); } } public class Test { public static void main(String[] args) { Animal animal = new Animal(); animal.move(); Dog dog = new Dog(); dog.move(); } }
输出结果为:
动物在移动 狗在奔跑
在上面的示例代码中,Animal类中定义了一个move()方法,输出“动物在移动”。而在Dog类中重写了该方法,输出“狗在奔跑”。当创建一个Animal对象和一个Dog对象,并调用它们的move()方法时,Animal对象输出“动物在移动”,而Dog对象输出“狗在奔跑”,说明子类中重写的方法优先于父类中的方法被调用。
3. 类的访问控制
3.1 访问控制的概念
3.1.1 访问控制的概念
访问控制是指限制类中成员的访问范围,以保护数据的安全性和完整性。Java中有4种访问控制修饰符:public、protected、default、private。其中,public表示公开的,可以在类的内部和外部访问;protected表示受保护的,可以在类的内部、外部同一包的类和子类中访问;default表示默认的,可以在类的内部和同一包的类中访问;private表示私有的,只能在类的内部访问。访问控制修饰符可以应用于类的成员变量、方法和构造方法,以实现对类的成员的访问控制。下表总结了访问控制修饰符的访问范围:
访问控制修饰符 | 类内部 | 同一包 | 子类 | 其他包 |
---|---|---|---|---|
public | ✔️ | ✔️ | ✔️ | ✔️ |
protected | ✔️ | ✔️ | ✔️ | ❌ |
default | ✔️ | ✔️ | ❌ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ |
例如,以下代码展示了一个类中成员的访问控制:
public class Person { public String name; // 公开的成员变量 protected int age; // 受保护的成员变量 String gender; // 默认的成员变量 private String address; // 私有的成员变量 public void sayHello() { // 公开的成员方法 System.out.println("Hello, my name is " + name); } protected void growUp() { // 受保护的成员方法 age++; } void changeGender() { // 默认的成员方法 if (gender.equals("male")) { gender = "female"; } else { gender = "male"; } } private void changeAddress(String newAddress) { // 私有的成员方法 address = newAddress; } }
3.2 访问控制的语法结构
3.2.1 访问修饰符
Java中有四种访问修饰符:public、protected、default和private。这些修饰符用于控制类、方法和变量的可见性和访问级别。
修饰符 | 同类 | 同包 | 子类 | 其他包 |
---|---|---|---|---|
public | ✔️ | ✔️ | ✔️ | ✔️ |
protected | ✔️ | ✔️ | ✔️ | ❌ |
default | ✔️ | ✔️ | ❌ | ❌ |
private | ✔️ | ❌ | ❌ | ❌ |
- public:公共的,可以被任何类访问。 - protected:受保护的,可以被同一包内的类和所有子类访问。 - default:默认的,可以被同一包内的类访问,不可以被其他包的类访问。 - private:私有的,只能被自己所在的类访问,其他类不能访问。
访问修饰符的使用要根据实际情况来选择,一般情况下,我们应该尽量使用最小的访问修饰符,以保证程序的安全性和可读性。
3.3 访问控制的权限控制
3.3.1 访问修饰符
访问修饰符是一种用于限制类、变量、方法和构造函数访问权限的关键字。Java中有4种访问修饰符:public、protected、default和private。
修饰符 | 同一类 | 同一包内 | 子类 | 其他包 |
---|---|---|---|---|
public | ✔ | ✔ | ✔ | ✔ |
protected | ✔ | ✔ | ✔ | ✖ |
default | ✔ | ✔ | ✖ | ✖ |
private | ✔ | ✖ | ✖ | ✖ |
- public:可以被任何类、方法和变量访问。 - protected:可以被同一类、同一包内的类、以及其他包中的子类访问。 - default:可以被同一类、同一包内的类访问。 - private:只能被同一类内的方法和变量访问。
在使用访问修饰符时,需要根据具体情况进行选择。一般情况下,应尽量使用最严格的访问修饰符,以保证程序的安全性和稳定性。
4. 类的多态
4.1 多态的概念
3.1.1 什么是多态
多态是面向对象编程的三大特性之一,指的是同一个类的实例在不同情况下表现出不同的行为。具体来说,就是子类可以重写父类的方法,从而实现对同一方法的不同实现,而调用该方法时会根据实际对象的类型来执行相应的实现。多态可以提高代码的灵活性和可扩展性,使得代码更加易于维护和修改。
举个例子,假设我们有一个动物类Animal,其中有一个方法eat(),然后我们派生出狗类Dog和猫类Cat,它们都继承自Animal类并重写了eat()方法。现在我们可以定义一个Animal类型的变量a,然后让它分别指向Dog和Cat的实例,然后调用它们的eat()方法,这时会根据实际指向的对象类型来执行相应的eat()方法,即狗会吃骨头,猫会吃鱼。
动物类ANIMAL | 狗类DOG | 猫类CAT |
---|---|---|
eat() | 吃东西 | 吃东西 |
4.2 多态的语法结构
3.1.2 多态的语法结构
多态是面向对象编程的一个重要特性,它可以让不同的对象对同一个方法作出不同的响应。在Java中,实现多态需要满足两个条件:继承和方法重写。具体地,需要满足以下语法结构:
class SuperClass { public void method() { // 父类方法的实现 } } class SubClass extends SuperClass { @Override public void method() { // 子类方法的实现 } } SuperClass obj1 = new SuperClass(); SuperClass obj2 = new SubClass(); obj1.method(); // 调用父类方法 obj2.method(); // 调用子类方法
在上述代码中,定义了一个父类SuperClass
和一个子类SubClass
,子类继承了父类的方法method()
并重写了该方法。在创建对象时,可以使用父类类型的引用指向子类对象,这样可以实现多态。当调用method()
方法时,实际上会根据对象的类型来调用对应的方法实现。
需要注意的是,多态只适用于实例方法,而不适用于静态方法或私有方法。此外,如果父类中的方法为私有方法,则子类无法重写该方法,因此也无法实现多态。
4.3 多态的应用场景
3.1.1 多态在实现接口时的应用
接口是Java中一种重要的多态机制,通过实现接口,一个类可以具有多种不同的行为方式。例如,一个电子产品类可以实现一个“可充电”接口和一个“不可充电”接口,从而使得这个类可以同时拥有不同的充电方式。在实际开发中,接口的应用非常广泛,可以用于实现各种不同的功能和特性。
以下是一个示例代码,展示了一个电子产品类如何实现“可充电”和“不可充电”接口:
// 可充电接口 interface Rechargeable { void recharge(); } // 不可充电接口 interface NonRechargeable { void useBattery(); } // 电子产品类 class ElectronicProduct implements Rechargeable, NonRechargeable { public void recharge() { System.out.println("正在充电..."); } public void useBattery() { System.out.println("正在使用电池..."); } } // 测试代码 public class Main { public static void main(String[] args) { ElectronicProduct product = new ElectronicProduct(); product.recharge(); // 正在充电... product.useBattery(); // 正在使用电池... } }
在上面的代码中,ElectronicProduct类实现了Rechargeable和NonRechargeable接口,从而可以同时拥有充电和使用电池的功能。在Main类中,我们可以创建一个ElectronicProduct对象,并调用其recharge()和useBattery()方法,从而实现不同的功能。
5. 类的内部类
5.1 内部类的概念
3.1.1 成员内部类
成员内部类是指定义在另一个类中的类,它与外部类有相同的访问权限。成员内部类可以访问外部类的所有成员变量和方法,包括私有的成员。在外部类的方法中,可以通过创建内部类的对象来访问内部类的成员。示例代码如下:
public class Outer { private int outerVar; public void outerMethod() { Inner inner = new Inner(); inner.innerMethod(); } class Inner { private int innerVar; public void innerMethod() { outerVar = 1; innerVar = 2; System.out.println("outerVar: " + outerVar + ", innerVar: " + innerVar); } } }
在上面的代码中,Inner
是 Outer
的成员内部类,它可以访问 Outer
的私有成员变量 outerVar
。在 outerMethod
中,我们创建了 Inner
的对象 inner
,并调用了它的方法 innerMethod
,在该方法中,我们可以访问 Outer
的成员变量 outerVar
和 Inner
的成员变量 innerVar
。
5.2 内部类的语法结构
1.
在Java中,内部类是定义在另一个类内部的类,它可以访问外部类的私有成员,而外部类无法访问内部类的成员。内部类可以分为成员内部类、局部内部类、匿名内部类和静态内部类。
2.
成员内部类是定义在另一个类的内部的非静态类,它可以访问外部类的所有成员,包括私有成员。定义成员内部类的语法结构如下:
class OuterClass { ... class InnerClass { ... } ... }
3.
局部内部类是定义在方法内部的内部类,它只能在该方法内部使用。定义局部内部类的语法结构如下:
class OuterClass { ... void methodName() { class InnerClass { ... } ... } ... }
4.
匿名内部类是没有名字的内部类,它通常用于创建实现某个接口或继承某个类的对象。定义匿名内部类的语法结构如下:
class OuterClass { ... interface InterfaceName { ... } ... void methodName() { InterfaceName obj = new InterfaceName() { ... }; ... } ... }
5.
静态内部类是定义在另一个类内部的静态类,它不能访问外部类的非静态成员,但可以访问外部类的静态成员。定义静态内部类的语法结构如下:
class OuterClass { ... static class InnerClass { ... } ... }
5.3 内部类的应用场景
3.1 内部类在事件驱动程序中的应用
事件驱动程序是一种常见的编程模式,它的核心思想是程序会等待某些事件的发生,然后执行相应的操作。在Java中,事件驱动程序通常使用监听器(Listener)来实现。内部类在这种场景下非常有用,因为它可以轻松地访问外部类的私有成员变量和方法。
例如,假设我们正在编写一个GUI程序,当用户单击某个按钮时,程序需要执行一些操作。我们可以创建一个按钮监听器的内部类,它会监听按钮的单击事件,然后执行相应的操作。代码示例:
public class MyGUI { private int count = 0; public void init() { JButton button = new JButton("Click me!"); button.addActionListener(new ButtonListener()); // add button to GUI } private class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent event) { count++; System.out.println("Button clicked " + count + " times."); } } }
在上面的代码中,我们创建了一个MyGUI类,它包含了一个私有成员变量count和一个init()方法。在init()方法中,我们创建了一个JButton实例,并创建了一个ButtonListener的实例作为按钮的监听器。ButtonListener是MyGUI的内部类,它可以轻松地访问MyGUI的私有成员变量count,并在按钮被单击时将count加1并输出到控制台上。
通过使用内部类,我们可以将GUI程序的逻辑分解为多个小的模块,每个模块都可以独立地处理自己的任务。这样可以使程序更加清晰、易于维护和扩展。