文章目录
类和对象
类和对象的理解
万物皆对象,客观存在的事物都是对象
-
类:类是对同一类事物抽象的描述
问:如何形成类?
答:将多个对象中的相同行为和相同属性组合在一起就形成了类
-
类和对象的关系:
- 抽象和具体的关系。类是抽象的,对象是具体的
- 类是创建对象的模板(或蓝图)
- 类是对象的抽象,对象是类的具体
类的定义
类的组成由属性和行为两部分组成
- 属性:属性对应类中的成员变量,成员变量定义在类中方法外
- 行为:行为对应方法中的成员方法(或者叫做实例方法 )
类的定义步骤:
- 定义类
- 编写类的成员变量
- 编写类的成员方法
类名 | 成员变量 | 成员方法 |
---|---|---|
Phone | brand & price | setMessage() & call() |
// 1. 定义一个Phone类
public class Phone{
// 2. 编写类的成员变量
String name;
int price;
// 3. 编写成员方法
public void call() {
System.out.println("打电话");
}
public void sendMessage() {
System.out.println("发短信");
}
}
类名 | 成员变量 | 成员方法 |
---|---|---|
GirlFriend | name & height | cook() & wash() & shopping |
// 1. 定义一个GirlFriend类
class GirlFriend {
// 2. 编写成员变量
String name;
double height;
// 3. 编写成员方法
// 做饭
public void cook() {
System.out.println("做的饭很好吃");
}
// 洗衣服
public void wash() {
System.out.println("洗衣服洗的好仔细呀!");
}
// 逛街
public void shopping() {
System.out.println("逛街她牵着你的小手不放")
}
}
对象的使用
- 创建对象的格式:(创建对象,也叫做实例化)
- 类名 对象名 = new 类名();
- 调用成员的格式:
- 对象名.成员变量名
- 对象名.成员方法名()
代码展示:
// 编写Phone的测试类(包含main方法的类就是测试类)
public class PhoneTest{
public static void main(String[] args) {
// 创建对象
Phone phone = new Phone();
// 访问对象的成员变量
System.out.println(phone.brand);
System.out.println(phone.price);
// 对对象的属性进行赋值
phone.brand = "华为";
phone.price = 1299;
// 访问对象中的属性
System.out.println(phone.brand);
System.out.println(phone.price);
// 调用对象的方法
phone.call();
phone.sendMessage();
}
}
// 编写GirlFriend的测试类
public class GirlFriend {
public static void main(String[] args) {
// 创建GirlFriend对象
GirlFriend girlFriend = new GirlFriend();
// 访问对象的属性
System.out.println(girlFriend.name); // null
System.out.println(girlFriend.height);// 0.0
girlFriend.name = "Lily";
girlFriend.height = 1.65;
System.out.println("My girlFriend's name is" + girlFriend.name + ",she's height is " + girlFriend.height);
}
}
练习:学生对象
需求:首先定义一个学生类,然后定义一个学生测试类,在学生测试类中通过对象完成成员变量和成员方法的使用
类名 | 成员变量 | 成员方法 |
---|---|---|
Student | name & age | 学习、做作业 |
代码展示:
// 编写学生测试类
public class StudentDemo {
// 编写main方法,main方法是程序的入口,能被JVM识别并执行
public static void main(String[] args) {
// 创建对象
Student student = new Student();
// 访问对象的成员变量
System.out.println(student.name + "," + student.age);
// 对对象中的属性进行赋值
student.name = "Jack";
student.age = 18;
System.out.println(student.name + "," + student.age);
// 调用对象中的方法
student.study();
student.doHomework();
}
}
// 定义一个Student类
class Student {
// 编写属性
String name;
int age;
// 编写成员方法
public void study() {
System.out.println("好好学习,天天向上");
}
public void doHomework() {
System.out.println("键盘敲烂,月薪过万");
}
}
对象内存图
单个对象内存图
-
成员变量使用过程
-
成员方法调用过程
-
总结:对象是new出来的,数组也是,数组和对象属于引用数据类型,引用类型的变量中保存的都是地址值,new出来的对象都在堆内存中,堆中的成员都有默认值.
多个对象内存图
-
成员变量使用过程
-
成员方法调用过程
-
总结:
- 多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自的内存区域中,每个对象的成员变量都是各用各的,互不相干,多个对象共用一份成员方法
多个对象指向同一块内存
- 总结:当多个对象的引用指向同一个内存空间,只要有任何一个对象修改了内存中的数据,随后,不论用哪个对象进行数据获取,都是修改后的数据
成员变量和局部变量
成员变量和局部变量的区别
不同处 | 成员变量 | 局部变量 |
---|---|---|
声明位置不同 | 类中方法外 | 方法内部或方法定义时的参数 |
内存中位置不同 | 堆内存 | 栈内存 |
声明周期不同 | 随着对象的存在而存在,随着对象的消失而消失 | 方法进栈时存在,方法弹栈时消失 |
初始值不同 | 有默认值 | 没有默认值 |
注意:当前类中的成员变量可以在当前类中的任意位置使用
封装
private关键字概述
private是一个权限修饰符,可用来修饰成员(成员变量或者成员方法)
-
被private修饰的成员,只能在当前类中访问,外部无法直接通过
对象名.成员变量名
访问。若想外部能够访问需提供getXxx()
方法和setXxx()
方法getXxx()
方法,用于获取对象的成员变量的值,方法用public修饰setXxx(形参)
方法,用于对对象的成员变量进行赋值,方法用public修饰
-
好处:提高了类成员的安全性,不让外部直接访问
private使用步骤
- 将类的成员变量用private修饰
- 提供对应的setXxx()方法和getXxx()方法
- 在外部通过对象名.setXxx(形参) 对对象中的属性进行赋值,对象名.getXxx()方法访问对象中的成员变量的值
代码展示:
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name,int age){
this.name = name;
if(age > 120 || age < 0) {
System.out.println("输入的年龄有误");
} else {
this.age = age;
}
}
public void setAge(int age) {
if(age < 0 || age > 120) {
System.out.println("输入的年龄有误");
}else {
this.age = age;
}
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void show() {
System.out.println("My name si " + name + ",My age is" + age);
}
}
class StudentTest{
public static void main(String[] args) {
new Student("Lily",18).show();
}
}
this关键字
- this修饰的变量用于指代成员变量,主要作用:区分局部变量和成员变量重名的问题
- 方法的形参若与成员变量同名,不带this修饰的变量指的是形参,而非成员变量。若想要访问到成员变量,可在方法体中使用this.成员变量。
- 方法的形参与成员变量未同名时,不带this修饰的变量指的是成员变量
- this代表调用方法的当前对象,就是说:当前谁调用了那个方法,则那个对象就是谁,this也就代表谁
this内存原理
封装思想
- 封装概述
- 封装是面向对象的三大特征之一(
继承、封装、多态
) - 封装是面向对象编程语言对客观世界的模拟,客观世界里的成员变量都是隐藏在对象内部的,外界是无法直接操作的
- 封装是面向对象的三大特征之一(
- 封装原则
- 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供对应的getXxx()方法、setXxx()方法来实现对隐藏信息的操作和访问被private修饰的成员变量
- 封装的体现
- 方法是封装,封装一段具有功能的代码,方便重复调用
- 类就是封装,把成员封装到一个类中,类是引用数据类型,可创建很多对象,可重用
- private关键字也是封装,它提高了类中成员的安全性,不让外部直接进行访问。
- 封装的好处
- 方法可重用
- 类可重用
- private可提高类被成员的安全性
构造方法
构造方法概述
构造方法是种特殊的方法
构造方法的作用:
- 创建对象
- 对成员变量(或者属性)进行初始化
格式:
// 构造方法的格式
public class 类名 {
[修饰符] 类名([形参列表]) {
.....
}
}
注意:”[]“方括号括起来的内容可有可无,可以省略。
构造方法和普通方法的区别
- 构造方法没有返回值,也没有Static
- 构造方法名和类名必须保持一致,不一致的不叫构造方法
- 创建(new)对象 时,会自动执行相匹配的构造方法。
构造方法的注意事项
-
构造方法的创建
- 在一个类中,若没有手写构造方法,系统默认会提供一个无参构造;若手写了,系统就不会再提供默认的无参构造了.
-
构造方法的重载
- 若手写了带参构造方法,仍需使用无参构造方法,就必须再在写一个无参构造方法
-
总结:当我们在手写构造方法时,建议先编写一个构造方法,然后再去编写需要的构造方法
拓展知识
- 构造方法中可以有return关键字,必须编写为return;
- 构造方法前的public修饰符可以省略,省略后默认为default
标准类制作
需求:定义学生类,要求在测试类中分别使用无参和带参构造方法来创建对象
要求:通过无参构造方法创建的对象通过setXxx方法实现对对象中的属性进行赋值,通过带参构造方法创建的对象直接进行赋值,并通过show方法分别展示两个对象中的数据
类名 | 成员变量 | 构造方法 | 成员方法 |
---|---|---|---|
Student | name & age | Student() & Student(String name,int age) | show() & setName(String name) & getName() & getAge() & setAge() |
代码展示:
// 1. 定义一个Student类
class Student{
// 2. 编写成员变量
private String name;
private int age;
// 3. 编写无参构造
public Student() {
}
// 4. 编写带参构造
public Student(String name,int age) {
this.name = name;
this.age = age;
}
// 5. 编写成员方法
// 5.1 setXxx()方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
// 对获取的到的实参的值进行过滤
if(age < 0 || age > 120) {
System.out.println("您输的年龄有误");
}else {
this.age = age;
}
}
// 5.2 getXxx()方法
public String getName() {
return name;
}
public int getAge(){
return age; // return this.age;
}
// 5.3 show方法
public void show(Student student) {
System.out.println(student + "该对象的姓名为" + name + ",年龄为" + age);
}
}
// 编写测试类(包含main方法的类就是测试类)
public class StudentTest {
public static void main(String[] args) {
// 创建Student对象 同时执行无参构造
Student student = new Student();
// 对对象中的属性进行赋值
student.setName("Jack");
student.setAge(18);
// 调用对象中的方法
student.show(student);
// 创建Studnet对象,同时执行带参构造
Student student1 = new Student("Lily",19);
// 调用对象中的方法
student1.show(student1);
}
}
运行截图: