java —— 面向对象(上)
一、类的封装
在 Java 中,封装是面向对象编程的三大基本特性之一(另外两个是继承和多态),封装是一种将对象的内部状态和实现细节隐藏起来,通过公共方法提供对这些状态的访问和修改的编程机制。它有助于提高代码的安全性、可维护性和模块化,是面向对象编程中非常重要的一个概念。
// 定义好一个类,实现封装
class Student {
// 定义两个私有属性
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String stuName) {
name = stuName;
}
public int getAge() {
return age;
}
public void setAge(int stuAge) {
//
if (stuAge <= 0) {
System.out.println("年龄不合法");
} else {
age = stuAge;
}
}
public void introduce() {
System.out.println("姓名:" + name + "\t" + "年龄:" + age);
}
}
// 调用上面封装好的代码
class Ex04 {
public static void main(String[] args) {
Student stu = new Student();
stu.setAge(-30);
stu.setName("小白");
stu.introduce();
stu.setName("大白");
stu.setAge(22);
stu.introduce();
}
}
(一)代码解释:
-
Student 类:
-
属性:
private String name;
:定义一个私有的字符串属性name
,用于存储学生的姓名。private int age;
:定义一个私有的整数属性age
,用于存储学生的年龄。
-
访问器和修改器方法(Getter 和 Setter):
-
public String getName()
和public void setName(String stuName)
:getName()
方法用于获取name
属性的值。setName(String stuName)
方法用于设置name
属性的值,将stuName
赋值给name
。
-
public int getAge()
和public void setAge(int stuAge)
:getAge()
方法用于获取age
属性的值。setAge(int stuAge)
方法用于设置age
属性的值,但在设置之前会检查stuAge
的值。if (stuAge <= 0) {...}
:如果stuAge
小于或等于 0,会输出 "年龄不合法",不修改age
属性;否则将stuAge
赋值给age
。
-
-
introduce
方法:public void introduce()
:- 输出学生的姓名和年龄,使用
System.out.println("姓名:" + name + "\t" + "年龄:" + age);
进行输出。
- 输出学生的姓名和年龄,使用
-
-
Ex04 类的
main
方法:-
创建对象:
Student stu = new Student();
:创建一个Student
类的新对象stu
。
-
设置和获取属性:
-
stu.setAge(-30);
:- 调用
setAge
方法,尝试将年龄设置为 -30,由于 -30 不合法,会输出 "年龄不合法"。
- 调用
-
stu.setName("小白");
:- 调用
setName
方法,将姓名设置为 "小白"。
- 调用
-
stu.introduce();
:- 调用
introduce
方法,输出学生的信息,此时年龄不会被修改,仍为默认值(这里默认为 0,因为int
类型的默认值是 0),输出类似于 "姓名:小白 年龄:0"。
- 调用
-
stu.setName("大白");
:- 再次调用
setName
方法,将姓名修改为 "大白"。
- 再次调用
-
stu.setAge(22);
:- 调用
setAge
方法,将年龄设置为 22,这是一个合法的年龄。
- 调用
-
stu.introduce();
:- 再次调用
introduce
方法,输出学生的信息,此时输出 "姓名:大白 年龄:22"。
- 再次调用
-
-
二、构造方法 and 构造方法的重载
(一)构造方法
class Person {
int age;
// 定义有参数的构造方法
public Person(int a) {
age = a;
}
public void speak() {
System.out.println("I am " + age + " years old!");
}
}
public class Ex06_03 {
public static void main(String[] args) {
Person p = new Person(20);
p.speak();
}
}
(二)构造方法的重载
class Person1 {
String name;
int age;
// 定义两个参数的构造方法
public Person1(String con_name, int con_age) {
name = con_name;
age = con_age;
}
// 定义一个参数的构造方法
public Person1(String con_name) {
name = con_name;
}
public void speak() {
System.out.println("大家好,我叫" + name + age);
}
}
public class Ex07_03{
public static void main(String[] args) {
Person1 p1 = new Person1("c的");
Person1 p2 = new Person1("aa",22);
p1.speak();
p2.speak();
}
}
代码解释:
-
Person1 类:
-
成员变量:
String name;
:定义一个字符串类型的成员变量,用于存储人的名字。int age;
:定义一个整数类型的成员变量,用于存储人的年龄。
-
构造方法:
-
两个参数的构造方法:
public Person1(String con_name, int con_age) {...}
:- 当使用
new Person1("aa", 22);
创建对象时,会调用此构造方法。 - 接收
con_name
和con_age
作为参数,将con_name
赋值给name
成员变量,将con_age
赋值给age
成员变量。
- 当使用
-
一个参数的构造方法:
public Person1(String con_name) {...}
:- 当使用
new Person1("c的");
创建对象时,会调用此构造方法。 - 仅接收
con_name
作为参数,将con_name
赋值给name
成员变量,而age
成员变量未被初始化,会采用其数据类型的默认值(int
的默认值为 0)。
- 当使用
-
-
speak 方法:
public void speak() {...}
:- 此方法用于输出该
Person1
对象的信息。 System.out.println("大家好,我叫" + name + age);
:将name
和age
拼接成一个字符串并输出。
- 此方法用于输出该
-
-
Ex07_03 类:
- main 方法:
-
public static void main(String[] args)
:程序的入口点。 -
创建对象:
-
Person1 p1 = new Person1("c的");
:- 创建一个
Person1
对象p1
,使用一个参数的构造方法,仅传递name
为"c的"
,age
为默认值 0。
- 创建一个
-
Person1 p2 = new Person1("aa", 22);
:- 创建一个
Person1
对象p2
,使用两个参数的构造方法,传递name
为"aa"
,age
为 22。
- 创建一个
-
-
调用方法:
-
p1.speak();
:- 调用
p1
对象的speak
方法,输出信息,由于p1
的age
未初始化,输出为"大家好,我叫c的0"
。
- 调用
-
p2.speak();
:- 调用
p2
对象的speak
方法,输出信息,输出为"大家好,我叫aa22"
。
- 调用
-
-
- main 方法:
三、this()关键字
(一)案例一
1. 指代当前对象
this
关键字用于指代当前正在操作的对象。在一个类的实例方法中,它可以用来访问该类的实例变量和实例方法,以区分局部变量和实例变量。
2. 解决命名冲突
- 当方法的参数或局部变量与实例变量同名时,使用
this
可以明确表示正在操作的是实例变量
下面的代码执行的是有参数的Person2,因为有this(),所有执行了实例变量的无参数
class Person2{
public Person2(){
System.out.println("无参数");
}
public Person2(String name){
this();
System.out.println("有参数");
}
}
public class Ex10_03 {
public static void main(String[] args) {
Person2 p = new Person2("biaobai");
}
}
没有this()关键字
class Person2{
public Person2(){
System.out.println("无参数");
}
public Person2(String name){
// this();
System.out.println("有参数");
}
}
public class Ex10_03 {
public static void main(String[] args) {
Person2 p = new Person2("biaobai");
}
}
(二)案例二
class Person3 {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void introduce() {
System.out.println("My name is " + this.getName());
}
}
class eww{
public static void main(String[] args) {
Person3 p3 = new Person3();
p3.setName("是我");
p3.introduce();
}
}
代码解释:
-
Person3 类:
-
属性:
private String name;
:- 这是一个私有属性,用于存储
Person3
对象的名字。因为是私有属性,只能在Person3
类内部访问,外部类无法直接访问。
- 这是一个私有属性,用于存储
-
方法:
-
public void setName(String name)
:- 这是一个公共方法,用于设置
Person3
对象的名字。 this.name = name;
:使用this
关键字,this.name
表示对象的name
属性,将传入的参数name
的值赋给对象的name
属性。
- 这是一个公共方法,用于设置
-
public String getName()
:- 这是一个公共方法,用于获取
Person3
对象的名字。 return this.name;
:返回对象的name
属性的值。
- 这是一个公共方法,用于获取
-
public void introduce()
:- 这是一个公共方法,用于让
Person3
对象进行自我介绍。 System.out.println("My name is " + this.getName());
:调用getName()
方法获取对象的名字,并将其输出。
- 这是一个公共方法,用于让
-
-
-
eww 类的 main 方法:
-
创建对象:
Person3 p3 = new Person3();
:创建一个Person3
类的新对象p3
。
-
调用方法:
-
p3.setName("是我");
:- 调用
p3
对象的setName
方法,将名字设置为"是我"
。
- 调用
-
p3.introduce();
:- 调用
p3
对象的introduce
方法,让p3
对象进行自我介绍,输出"My name is 是我"
。
- 调用
-
-
四、static()关键字
(一)静态变量
class Student1 {
// 定义成员变量为静态,也就是只有一个赋值,不会发生重新赋值
static String schoolName;
}
public class Ex12_03 {
public static void main(String[] args) {
Student1 stu1 = new Student1();
Student1 stu2 = new Student1();
Student1.schoolName = "我的小白";
System.out.println("我的名字是1:" + Student1.schoolName);
System.out.println("我的名字是2:" + Student1.schoolName);
}
}
(二)静态方法
class Person4{
// 静态方法
public static void sayHello(){
System.out.println("hello");
}
// 非静态方法
public void sayHello2(){
System.out.println("hello2");
}
}
public class Ex13_03 {
public static void main(String[] args) {
// 可以直接调用,不需要创建对象
Person4.sayHello();
Person4 p4 = new Person4();
p4.sayHello2();
}
}
(三)静态代码块
1、静态代码块使用 static
关键字和花括号 {}
来定义,并且它会在类加载时执行,只执行一次。例如:
class MyClass {
static {
// 静态代码块中的代码
System.out.println("这是一个静态代码块");
}
}
2、可以看到没有main函数,依然可以输出
class Ex14_03 {
// 静态代码块
static {
System.out.println("测试类的静态代码块执行了");
}
3、不加载类不会执行static
class Ex14_03 {
// 静态代码块
static {
System.out.println("测试类的静态代码块执行了");
}
public static void main(String[] args) {
// 下面的代码创建两个Person对象
// Person5 p1 = new Person5();
// Person5 p2 = new Person5();
}
}
class Person5{
static String country;
// 静态代码块
static {
country = "小白";
System.out.println("Person5的静态代码块"+country);
}
}
4、加载类,static执行
class Ex14_03 {
// 静态代码块
static {
System.out.println("测试类的静态代码块执行了");
}
public static void main(String[] args) {
// 下面的代码创建两个Person对象
Person5 p1 = new Person5();
Person5 p2 = new Person5();
}
}
class Person5{
static String country;
// 静态代码块
static {
country = "小白";
System.out.println("Person5的静态代码块"+country);
}
}
五、内部类
(一)成员内外部类
1、外部类
class Outer {
private int num = 4;
// 定义了一个成员方法,方法中访问内部类
public void test() {
Inner inner = new Inner();
inner.show();
}
// 定义了一个成员内部类
class Inner {
void show() {
// 在成员内部类分方法中访问外部类的成员变量
System.out.println("num=" + num);
}
}
}
public class Ex16_03 {
public static void main(String[] args) {
Outer outer = new Outer(); // 创建外部类对象
outer.test();
}
}
2、内部类
成员内部类是定义在外部类内部的类,作为外部类的一个成员存在,因此它可以使用外部类的所有成员(包括私有成员)。
外部类名.内部类名 变量名 = new 外部类名() .new 内部类名();
public class Ex17_03 {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}
(二)静态内部类
class Outer1 {
private static int num = 6;
// 静态内部类
static class Inner {
void show() {
System.out.println("num=" + num);
}
}
}
public class Ex18_03 {
public static void main(String[] args) {
Outer1.Inner inner = new Outer1.Inner();
inner.show();
}
}
(三)方法内部类
class Outer2 {
private int num = 4;
public void test() {
// 在方法中定义内部类
class Inner {
void show() {
System.out.println("num=" + num);
}
}
Inner in = new Inner();
in.show(); // 这里调用show()方法,所以下面直接outer2.test();就可以拿到返回值
}
}
public class Ex19_03 {
public static void main(String[] args) {
Outer2 outer2 = new Outer2();
outer2.test();
}
}