类和对象基础
1. 类和对象基础
什么是对象? 什么是类?
如何定义一个类?类中有什么 ?
对象是一个实体, 类是用来描述实体的
定义类的格式: class为定义类的关键字,ClassName为类的名字,{}中为类的主体。
// 创建类 class ClassName{ field; // 字段(属性) 或者 成员变量 method; // 行为 或者 成员方法 }
类中有属性和成员方法, 属性描述对象的特性 成员方法描述对象具备哪些行为
以下面这个WashMachine类为例:
class WashMachine { //属性 、 字段 、成员变量:这些成员变量是定义在方法外部 类的内部的 public String brand; // 品牌 public String type; // 型号 public double weight; // 重量 public double length; // 长 public double width; // 宽 public double height; // 高 public String color; // 颜色 //成员方法 -> 行为 public void washClothes(){ // 洗衣服 System.out.println("洗衣功能"); } public void dryClothes(){ // 脱水 System.out.println("脱水功能"); } public void setTime(){ // 定时 System.out.println("定时功能"); } }
成员变量品牌,型号,重量... 描述洗衣机实体的属性/特性
成员方法洗衣服 脱水 定时,描述洗衣机实体具备的行为
定义了一个类相当于自己定义了一种新的类型,可以用这个新的类型创建变量
class WashMachine { //属性 、 字段 、成员变量:这些成员变量是定义在方法外部 类的内部的 public String brand; // 品牌 public String type; // 型号 public double weight; // 重量 public double length; // 长 public double width; // 宽 public double height; // 高 public String color; // 颜色 //成员方法 -> 行为 public void washClothes(){ // 洗衣服 System.out.println("洗衣功能"); } public void dryClothes(){ // 脱水 System.out.println("脱水功能"); } public void setTime(){ // 定时 System.out.println("定时功能"); } public static void main(String[] args) { // 使用WashMachine类创建变量 WashMachine washMachine; } }
如何创建一个对象?对象中有什么 ?
使用描述该对象的类 + new关键字 创建对象:
Dog dog1 = new Dog();
new Dog(); 创建(实例化) 对象
对象根据Dog类创建 ——》用Dog类定义的变量dog1存储对象地址, 此时dog1称为对象的引用 简称引用
class Dog { // 字段 / 属性 / 成员变量 public String name; public int age; // 行为 / 成员方法 public static void bark() { System.out.println("汪"); } } public class TestDemo { public static void main(String[] args) { // 创建对象: Dog dog1 = new Dog(); Dog dog2 = new Dog(); } }
对象内部只存储成员变量
new关键字创建对象,具体执行过程是什么 ?
如何访问对象的属性和方法 ?
通过对象的引用加点号 访问对象的属性和方法
例子:
class Dog { // 字段 / 属性 / 成员变量 public String name; public int age; // 行为 / 成员方法 public static void bark() { System.out.println("汪"); } } public class TestDemo { public static void main(String[] args) { Dog dog1 = new Dog(); // 3. 访问对象属性与方法 dog1.age = 10; dog1.name = "大黄"; System.out.println(dog1.name); System.out.println(dog1.age); dog1.bark(); } }
练习: 使用类和对象知识,交换两个值
class MyValue { int value; } public class TestDemo { public static void main(String[] args) { MyValue num1 = new MyValue(); MyValue num2 = new MyValue(); num1.value = 1; num2.value = 2; System.out.printf("交换前 ---> num1 = %d num2 = %d\n",num1.value,num2.value); Swap(num1,num2); System.out.printf("交换后 ---> num1 = %d num2 = %d\n",num1.value,num2.value); } public static void Swap(MyValue num1, MyValue num2) { int tmp = num1.value; num1.value = num2.value; num2.value = tmp; } }
2. this引用
什么是this引用 ?
谁调用成员方法 谁就是this引用
例子:
public class Date { public int year; public int month; public int day; // this引用是隐藏参数 可以自己加 public void setDay(Date this,int y, int m, int d) { this.year = y; this.month = m; this.day = d; } public void printDate(Date this) { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date date1 = new Date(); Date date2 = new Date(); // 不能自己传递当前调用方法的对象引用 // date1.setDay(date1,1,1,1); date1.setDay(1,1,1); date2.setDay(2,2,2); date1.printDate(); date2.printDate(); } }
注意:
this引用是隐藏参数 可以自己加, 但是不能自己传递当前调用方法的对象引用
this引用有哪些作用 ?
1. this.成员变量
2. this.成员方法
3. this() 调用构造函数
1 2 很好理解 this是对象的引用 通过点号访问对象的属性和方法,3 在构造方法中介绍
3. 构造方法
一共有几种初始化对象属性的方法 ?
1. 默认初始化
使用new关键字创建对象 开辟空间后 会根据数据类型分配一个默认的值
public class Date { public int year; public int month; public int day; // this引用是隐藏参数 可以自己加 public void setDay(Date this,int y, int m, int d) { this.year = y; this.month = m; this.day = d; } public void printDate(Date this) { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date date1 = new Date(); date1.printDate(); // 0 0 0 } }
2. 就地初始化
public class Date { // 就地初始化 // 声明成员变量时赋值 public int year = 1; public int month = 1; public int day = 1; // this引用是隐藏参数 可以自己加 public void setDay(Date this,int y, int m, int d) { this.year = y; this.month = m; this.day = d; } public void printDate(Date this) { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date date1 = new Date(); date1.printDate(); } }
3. 使用构造方法进行初始化
什么是构造方法 ? 构造方法有什么用 ?
构造方法是类中特殊成员方法 用来对对象的成员变量进行初始化
如何定义构造方法 ?
写法: 方法名与类名相同没有返回值
public class Date { public int year; public int month; public int day; // 构造方法: public Date() { this.year = 1; this.month = 1; this.day = 1; } public void setDay(Date this,int y, int m, int d) { this.year = y; this.month = m; this.day = d; } public void printDate(Date this) { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date date1 = new Date(); date1.printDate(); } }
构造方法什么时候调用的 ?
new创建对象时调用构造方法 且只调用一次
new对象大致过程:
首先给对象分配内存,然后编译器自动调用合适的构造方法(构造方法可以重载)给对象进行初始化,这里的合适指,编译器会根据参数选取构造方法进行初始化
查看代码
class Date { public int year; public int month; public int day; public Date(int y,int m,int d) { this.year = y; this.month = m; this.day = d; } public Date() { this.year = 1; this.month = 1; this.day = 1; } public void print(Date this) { System.out.print(this.year + " " + this.month + " " + this.day); System.out.println(); } } public class Test { public static void main(String[] args) { // 调用带有3个参数的构造方法 Date date1 = new Date(2,2,2); date1.print(); // 调用带有无参构造 Date date2 = new Date(); date2.print(); } }
如何在类中调用其他构造 ?
构造方法中,可以通过this调用其他构造方法
注意: 使用this调用必须放在当前构造方法的第一行,this调用也是根据参数选取构造方法进行调用
查看代码
public class Date { public int year; public int month; public int day; // 默认生成的构造方法 public Date(){ // 调用三个参数的构造方法 this(2024,1,24); } public Date(int year,int month,int day){ this.year = year; this.month = month; this.day = day; } public void printDate(Date this) { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date date1 = new Date(); date1.printDate(); } }
构造方法是new对象时调用的 所以一定会被调用 那么为什么不写构造方法并没有报错 ?
如果没有自己定义构造方法,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参且没有具体的实现
如果自己定义了构造方法,编译器将不再生成
查看代码
public class Date { public int year; public int month; public int day; // 默认生成的构造方法 public Date(){ } public void setDay(Date this,int y, int m, int d) { this.year = y; this.month = m; this.day = d; } public void printDate(Date this) { System.out.println(this.year + "/" + this.month + "/" + this.day); } public static void main(String[] args) { Date date1 = new Date(); date1.printDate(); } }
4. 封装
什么是封装 ?在java中如何实现封装 ?
封装就是隐藏类内部实现的细节, 只对外提供一些开发的接口
在java中使用 private关键字实现
class Student { // private修饰的成员变量和方法 只能在当前类中使用 private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } // 只对外提供一些开发的接口 public String getName() { return this.name; } public int getAge() { return this.age; } } class Test { public static void main(String[] args) { Student student1 = new Student("小白",19); System.out.println(student1.getName()); } }
5. static 关键字
static关键字的作用是什么 ?
为了不创建对象去访问成员变量和方法,static修饰的静态成员变量和方法使用类名+点号访问
public class Test { public int a = 1; public void test1() { System.out.println("test1: 非静态方法"); } public static int b = 2; public static void test2() { System.out.println("test2: 静态方法"); } public static void main(String[] args) { // 非静态成员方法和变量 需要对象去访问成员变量和方法 Test obj = new Test(); obj.test1(); System.out.println(obj.a); // static修饰的静态成员变量和方法 不需要对象 使用类名 + 点号访问 Test.test2(); System.out.println(Test.b); } }
注意:
1. 虽然使用类实例化对象的引用也可以访问静态成员变量,但是不合适不建议
2. 静态成员属于类的属性,存储在方法区 且只存储一份
3. 静态的成员变量 随着类被加载而创建 类被销毁而销毁
4. static 只能修饰成员变量和方法,不能修饰局部变量
静态方法中是否可以使用非静态成员变量和方法 ?
不可以,static修饰的成员属于类 使用类名访问,而不是用对象的引用
所以不会传递this引用, 没有this引用 就不能调用普通成员 因为普通成员调用需要对象,参考例4
但是 非静态方法中可以使用静态成员,参考例3
public class Test { public int a = 1; public void test1() { System.out.println("test1: 非静态方法"); } public static int b = 2; public static void test2() { System.out.println("test2: 静态方法"); } // 3. 非静态方法中可以使用静态成员 public void test3() { test2(); System.out.println(b); } // 4. 但是 静态方法中不能使用非静态成员变量和方法 public static void test4() { // 报错 ! /*System.out.println(this.a); this.test1();*/ } public static void main(String[] args) { // 1. 非静态成员方法和变量 需要对象去访问成员变量和方法 /*Test obj = new Test(); obj.test1(); System.out.println(obj.a);*/ // 2. static修饰的静态成员变量和方法 不需要对象 使用类名 + 点号访问 /*Test.test2(); System.out.println(Test.b);*/ // 3. /*Test obj = new Test(); obj.test3();*/ // 4. //Test.test4(); } }
6. 代码块和内部类
class TestStatic { public static int staticNum = 100; public int data1 = 10; { // 构造代码块 || 实例代码块 // 创建对象时才会执行 System.out.println("实例代码块被执行了...."); data1 = 1000;// 1. 构造代码块一般情况下 用来初始化 非静态的数据成员 //staticNum = 1000000; 2. 构造代码块 也可以初始化静态的数据成员 } // 3. 静态代码块 只能初始化静态成员 // JVM 加载类时执行 static { System.out.println("静态代码块被执行了...."); staticNum = 9999; // data1 = 20; } static { staticNum = 20; } public TestStatic() { System.out.println("执行构造方法....."); } // 4. 执行顺序: 静态 -> 实例 -> 构造方法 public static void main1(String[] args) { TestStatic testStatic = new TestStatic(); } // 5. 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行 public static void main(String[] args) { System.out.println(TestStatic.staticNum); } }
// 静态内部类 /* class Outer { public int a = 1; public static int b = 2; // 1. 把静态内部类当作类的成员 static class innerClass { // 3. 内部类中无法直接访问 外部类非静态的成员变量 public void get() { // 因为需要对象的引用 Outer outer = new Outer(); System.out.println(outer.a); System.out.println(b); System.out.println("innerClass::func"); } } // 2. 方法2: 实例化静态内部类对象 public void test() { innerClass innerClass = new innerClass(); innerClass.get(); } } public class Main { public static void main(String[] args) { // 2. 方法1: 实例化静态内部类对象 */ /* Outer.innerClass innerClass = new Outer.innerClass(); innerClass.get(); Outer outer = new Outer(); outer.test(); *//* } }*/ // 实例内部类 /*class Outer { public int a = 1; public static int b = 2; // 1. 实例内部类定义 class innerClass { // 2. 实例内部类中不能定义 静态成员变量 // 因为实例内部类 看作是类的成员 会被对象引用进行调用 //public static int a = 1; // 3. 如果一定要定义 必须加final修饰 public static final int b = 3; public void get() { // 5. 指定访问外部类成员 // 方法1: 外部类对象引用 Outer outer = new Outer(); System.out.println(outer.a); // 方法2: 外部类.this System.out.println(Outer.this.a); System.out.println("innerClass::func"); } } public void test() { innerClass innerClass = new innerClass(); innerClass.get(); } } public class Main { public static void main(String[] args) { *//*Outer outer = new Outer(); outer.test();*//* // 4. 实例内部类 实例化对象 Outer.innerClass innerClass = new Outer().new innerClass(); innerClass.get(); } }*/ // 匿名内部类 /* interface InterfaceA { void fun(); } class Test implements InterfaceA { @Override public void fun() { System.out.println("test"); } } public class Main { public static void main(String[] args) { InterfaceA interfaceA = new InterfaceA() { @Override public void fun() { System.out.println("test2"); } }; interfaceA.fun(); } } */
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现