Java类与对象
文章目录
1. 类与对象的初步认知
面向过程:
面向对象:
2. 类和类的实例化
类就是一类对象的统称。对象就是这一类具体化的一个实例。
总的来说:类相当于一个模板,对象是/由模板产生的样本。一个类,可以产生无数的对象。
基本语法:
// 创建类
class <class_name>{
field;//成员属性
method;//成员方法
}
// 实例化对象
<class_name> <对象名> = new <class_name>();
class为定义类的关键字,ClassName为类的名字,{}中为类的主体。
类中的元素称为:成员属性。类中的函数称为:成员方法。
示例:
class Person {
public int age;//成员属性 实例变量
public String name;
public String sex;
public void eat() {//成员方法
System.out.println("吃饭!");
}
public void sleep() {
System.out.println("睡觉!");
}
}
类的实例化:用类类型创建对象的过程,称为类的实例化
- 类只是一个模型一样的东西,限定了类有哪些成员.
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
- 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
class Person {
public int age;//成员属性 实例变量
public String name;
public String sex;
public void eat() {//成员方法
System.out.println("吃饭!");
}
public void sleep() {
System.out.println("睡觉!");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();//通过new实例化对象
person.eat();//成员方法调用需要通过对象的引用调用
person.sleep();
//产生对象 实例化对象
Person person2 = new Person();
Person person3 = new Person();
}
}
# 3. 类的成员
类的成员可以包含以下:字段、方法、代码块、内部类和接口等。且分为普通的成员变量(public int age)和静态成员变量(public static int age)
## 3.1 字段/属性/成员变量
在类中, 但是方法外部定义的变量. 这样的变量我们称为 “字段” 或 “属性” 或 “成员变量”(三种称呼都可以, 一般不会严格区分).
class Person {
public String name; // 字段
public int age;
}
class Test {
public static void main
(String[] args) {
Person person = new Person();
System.out.println(person.name);
System.out.println(person.age);
}
}
简单来说 字段=属性=成员变量 他们是**方法外**部**定义的“变量”。**
**注意事项:**
使用 . 访问对象的字段.
“访问” 既包含读, 也包含写.
对于一个对象的字段如果没有显式设置初始值, 那么会被设置一个默认的初值.
**默认值规则:**
对于各种数字类型, 默认值为 0.
对于 boolean 类型, 默认值为 false.
对于引用类型(String, Array, 以及自定制类), 默认值为 null
## 3.1.1认识 null
null 在 Java 中为 “空引用”, 表示不引用任何对象. 类似于 C 语言中的空指针. 如果对 null 进行 . 操作就会引发异常.
## 3.1.2字段就地初始化
class Person {
public String name = “张三”;
public int age = 18;
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
System.out.println(person.age);
}
}
3.2 方法 (method)
就是我们曾经讲过的方法.
用于描述一个对象的行为.
class Person {
public int age = 18;
public String name = "张三";
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "岁");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
person.show();
}
}
这样的 show 方法是和 person 实例相关联的. 如果创建了其他实例, 那么 show 的行为就会发生变化
class Person {
public int age = 18;
public String name = “张三”;
public void show() {
System.out.println(“我叫” + name + “, 今年” + age + “岁”);
}
}
public class TestDemo {
public static void main(String[] args) {
Person person2 = new Person();
person2.name = “李四”;
person2.age = 20;
person2.show();
}
}
## 3.3 static 关键字
1、修饰属性
2、修饰方法
3、代码块(本课件中会介绍)
4、修饰类(后面讲内部类会讲到)
a) 修饰属性,Java静态属性和类相关, 和具体的实例无关. 换句话说, 同一个类的不同实例共用同一个静态属性.
class TestDemo1{
public int a;
public static int count;
}
public class TestDemo {
public static void main(String[] args) {
TestDemo1 t1 = new TestDemo1();
t1.a++;
TestDemo1.count++;
System.out.println(t1.a);
System.out.println(TestDemo1.count);
System.out.println(“============”);
TestDemo1 t2 = new TestDemo1();
t2.a++;
TestDemo1.count++;
System.out.println(t2.a);
System.out.println(TestDemo1.count);
}
}
示例代码内存解析:count被static所修饰,所有类共享。且不属于对象,访问方式为:类名 . 属性。
t1和t2在堆上的地址调用不一样 而在堆调用方法区时确实调用的同一个对象count
相当于t2中的count还是t1中的count。
b) 修饰方法
如果在任何方法上应用 static 关键字,此方法称为静态方法。
- 静态方法属于类,而不属于类的对象。
- 可以直接调用静态方法,而无需创建类的实例。
- 静态方法可以直接访问静态数据成员,并可以更改静态数据成员的值。
class TestDemo{
public int a;
public static int count;
public static void change() {
count = 100;
//a = 10; error 不可以访问非静态数据成员
}
}
public class Main{
public static void main(String[] args) {
TestDemo.change();//无需创建实例对象 就可以调用
System.out.println(TestDemo.count);
}
}
输出结果:100
注意事项:
1.在类的成员方法中不可以用static来创建变量,static只能在类里面定义和方法外部定义。
例如:
class Person {
public void sleep() {
static int size = 0;//error
System.out.println("睡觉!");
}
}
3.4方法调用易错区分
静态变量可以不用实例化(new),可以直接通过类.来进行操作:
class TestDemo1{
public int a;
public static int count;
}
public class TestDemo {
public static void main(String[] args) {
TestDemo1.count = 10;
System.out.println(TestDemo1.count);
}
}
在类中普通方法的内部 不能够定义静态的变量。
在普通方法内部可以调用静态方法
在静态方法内部可以调用静态方法 但是不可以调用普通方法
# 4. 封装
**什么叫封装?**
在我们写代码的时候经常会涉及两种角色: **类的实现者**和**类的调用者**.
封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的, 只要知道如何使用类就行了.
这样就降低了类使用者的学习和使用成本, 从而降低了复杂程度.
## 4.1 [private](https://so.csdn.net/so/search?q=private&spm=1001.2101.3001.7020)实现封装
private/ public 这两个关键字表示 “访问权限控制” .
被 public 修饰的成员变量或者成员方法, 可以直接被类的调用者使用.
被 private 修饰的成员变量或者成员方法, 不能被类的调用者使用.
class Person {
private String name = “张三”;
private int age = 18;
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "岁");
}
}
class Test {
public static void main(String[] args) {
Person person = new Person();
person.show();
}
}
此时字段已经使用 private 来修饰. 类的调用者(main方法中)不能直接使用. 而需要借助 show 方法. 此时类的使用者就不必了解 Person 类的实现细节.
同时如果类的实现者修改了字段的名字, 类的调用者不需要做出任何修改(类的调用者根本访问不到 name, age这样的字段).
注意事项:
private 不光能修饰字段, 也能修饰方法
通常情况下我们会把字段设为 private 属性, 但是方法是否需要设为 public, 就需要视具体情形而定. 一般我们希望一个类只提供 “必要的” public 方法, 而不应该是把所有的方法都无脑设为 public.
系统自动封装方法:
结果演示:
## 4.2 getter和setter方法
当我们使用 private 来修饰字段的时候, 就无法直接使用这个字段了.
而是要使用set和get方法来引用他
```java
class Person {
private String name;//实例成员变量
private int age;
public void setName(String name){
//name = name;//不能这样写
this.name = name;//this引用,表示调用该方法的对象
}
public String getName(){
return name;
}
public void show(){
System.out.println("name: "+name+" age: "+age);
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();//类的实例化
person.setName("caocao");//通过setName调用类中private中的name
String name = person.getName();//创建字符串变量name赋值为getName中获取的值 多余
System.out.println(name); //多余可省
person.show();//调用类中的方法
}
}
最简写法:
即在主函数main
这里我们用person.setName();
来引用我们的类
用person.show
来输出我们的结果
注意事项:
getName
即为 getter
方法, 表示获取这个成员的值.
setName
即为setter
方法, 表示设置这个成员的值 .
当set方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this, 相当于自赋值. this 表示当前实例的引用.
不是所有的字段都一定要提供 setter / getter 方法, 而是要根据实际情况决定提供哪种方法.
在 IDEA 中可以使用 alt + insert (或者 alt + F12) 快速生成 setter / getter 方法. 在 VSCode 中可以使用鼠标右键菜单 -> 源代码操作 中自动生成 setter / getter 方法.
5.构造方法
5.1 基本语法
每一个类必须有一个构造方法 如果我们没写 idea会自动帮我们写一个不带参数的构造方法
构造方法是我们调用类 并使用它更方便了
class Person {
private String name;//实例成员变量
private int age;
private String sex;
//默认构造函数 构造对象
public Person() {
this.name = "caocao";
this.age = 10;
this.sex = "男";
}
//带有3个参数的构造函数 注意这里时public 不是private
public Person(String name,int age,String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
我们从:
Person p1 = new Person();//调用不带参数的构造函数 如果程序没有提供会调用不带参数的构造函数
p1.name = "qiqi";
p1.age = 18;
p1.sex = "女";
p1.show();
到
Person p2 = new Person3("zhangfei",80,"男");//调用带有3个参数的构造函数
p2.show();
对比两个代码内容可以看出,我们用构造方法来调用我们的类并赋值比我们不使用构造方法来赋值要方便的多。
构造方法是一种特殊方法, 使用关键字new实例化新对象时会被自动调用, 用于完成初始化操作.
分辨是普通方法还是构造方法:
构造方法就是方法里面用了**this.**来赋初值且方法名称和类相同(用的是public) 构造方法可以无参数 但是一旦有一个构造方法有了参数 那么其余的构造方法就至少得有一个参数32
new 执行过程:
为对象分配内存空间
调用对象的构造方法
语法规则:
1.方法名称必须与类名称相同
2.构造方法没有返回值类型声明
3.每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)
注意事项:
如果类中没有提供任何的构造函数,那么编译器会默认生成一个不带有参数的构造函数
若类中定义了构造方法,则默认的无参构造将不再生成
构造方法支持重载. 规则和普通方法的重载一致.
class Person {
private String name;//实例成员变量
private int age;
private String sex;
//默认构造函数 构造对象
public Person() {
this.name = "caocao";
this.age = 10;
this.sex = "男";
}
//带有3个参数的构造函数 注意这里时public 不是private
public Person(String name,int age,String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class TestDemo {
public static void main(String[] args) {
Person p1 = new Person();//调用不带参数的构造函数 如果程序没有提供会调用不带参数的构造函数
p1.show();
Person p2 = new Person("zhangfei",80,"男");//调用带有3个参数的构造函数
p2.show();
}
}
5.2 this关键字
this表示当前对象引用(注意不是当前对象). 可以借助 this 来访问对象的字段和方法.
6. 认识代码块
字段的初始化方式有:
- 就地初始化
- 使用构造方法初始化
- 使用代码块初始化
前两种方式前面已经学习过了, 接下来我们介绍第三种方式, 使用代码块初始化我们的类成员.
6.1 什么是代码块
使用 {} 定义的一段代码.
根据代码块定义的位置以及关键字,又可分为以下四种:
- 普通代码块(实例代码块)
- 构造块
- 静态块
- 同步代码块
类的调用顺序:
- 静态代码块(只会被执行一次)
- 实例代码块
- 构造方法
- 普通方法
6.2 普通代码块(实例代码块)
普通代码块:定义在方法中的代码块.
{
System.out.println("实例代码块!");
}
6.3 构造代码块(实例代码块)
构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
class Person{
private String name;//实例成员变量
private int age;
private String sex;
public Person() {
System.out.println("I am Person init()!");
}
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class TestDemo {
public static void main(String[] args) {
Person p1 = new Person();
p1.show();
}
}
6.4 静态代码块
使用static定义的代码块。一般用于初始化静态成员属性。
static {
System.out.println("静态代码块!");
}
静态代码块 **只被执行**了**一次** 在创建第二个对象时 静态代码块就不会执行了
# 7. 补充说明
## 7.1 toString方法
可以使用 toString 这样的方法来将对象自动转成字符串.
就相当于系统帮我们写类中的`p1.show();`类中的方法
注意事项:
- toString 方法会在 println 的时候被自动调用.
- 将对象转成字符串这样的操作我们称为 **序列化.**
- toString 是 Object 类提供的方法, 我们自己创建的 Person 类默认继承自 Object 类, 可以重写 toString 方法实现我们自己版本的转换字符串方法. (
- @Override 在 Java 中称为 “注解”, 此处的 @Override 表示下面实现的 toString 方法是重写了父类的方法.
- IDEA快速生成Object的toString方法快捷键:alt+f12(insert)
序列化:对象–>字符串
反序列化:字符串–>对象
自动生成类成员打印的方法:
选择toString()
结果演示:
如此我们函数变自动将对象转化为字符串了
## 7.2 匿名对象
匿名只是表示没有名字的对象.
- 没有引用的对象称为匿名对象.
- 匿名对象只能在创建对象时使用.
- 如果一个对象**只**是**用一次**, **后面不**需要**用了**, 可以考虑使用匿名对象.
代码示例:
class Person {
private String name;
private int age;
public Person(String name,int age) {
this.age = age;
this.name = name;
}
public void show() {
System.out.println(“name:”+name+" " + “age:”+age);
}
}
public class Main {
public static void main(String[] args) {
new Person(“caocao”,19).show();//通过匿名对象调用方法
}
}
结果:
name:caocao age:19
**内容重点总结**
- 一个类可以产生无数的对象,类就是模板,对象就是具体的实例。
- 类中定义的属性,大概分为几类:类属性,对象属性。其中被static所修饰的数据属性称为类属性, static修饰的方法称为类方法,**特点是不依赖于对象,我们只需要通过类名就可以调用其属性或者方法。**
- 静态代码块优先实例代码块执行,实例代码块优先构造函数执行。
- this关键字代表的是当前对象的引用。并不是当前对象
int age;
public Person(String name,int age) {
this.age = age;
this.name = name;
}
public void show() {
System.out.println(“name:”+name+" " + “age:”+age);
}
}
public class Main {
public static void main(String[] args) {
new Person(“caocao”,19).show();//通过匿名对象调用方法
}
}
结果:
123
name:caocao age:19
**内容重点总结**
- 一个类可以产生无数的对象,类就是模板,对象就是具体的实例。
- 类中定义的属性,大概分为几类:类属性,对象属性。其中被static所修饰的数据属性称为类属性, static修饰的方法称为类方法,**特点是不依赖于对象,我们只需要通过类名就可以调用其属性或者方法。**
- 静态代码块优先实例代码块执行,实例代码块优先构造函数执行。
- this关键字代表的是当前对象的引用。并不是当前对象