- 1. 类与对象的初步认知
- 2. 类和类的实例化
- 3. 类的成员
- 3.1 字段/属性/成员变量
- 3.2 方法 (method):用于描述一个对象的行为.
- 3.3 static 关键字
- 4. 封装
- 4.1 private实现封装
- 4.2 getter和setter方法
- 5. 构造方法
- 5.1 基本语法
- 5.2 this关键字
- 6. 认识代码块
- 6.1 什么是代码块
- 6.2 普通代码块:定义在方法中的代码块
- 6.3 构造代码块
- 6.4 静态代码块
- 7. 补充说明
- 7.1 toString方法
- 7.2 匿名对象
- 8.重点总结
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
JAVA是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
面向过程注重的是过程,在整个过程中所涉及的行为,就是功能。
面向对象注重的是对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来
面向过程: 1.把冰箱打开 2. 把大象放入 3. 冰箱关起来 面向对象: 打开冰箱,储存,关闭都是对冰箱的操作,是冰箱的行为。冰箱就是一个对象,所以只要操作冰箱所具备的功能,都要定义在冰箱中。
类就是一类对象的统称。对象就是这一类具体化的一个实例。
简单的例子:我们做月饼的模子就是一个类,而通过这个模子可以做出月饼,那么在这个例子当中,类就是那个模子,而月饼就是那个对象,所以月饼就是一个实体。一个模子可以实例化无数个对象。
总的来说:类相当于一个模板,对象是由模板产生的样本。一个类,可以产生无数的对象。
声明一个类就是创建一个新的数据类型,而类在 Java 中属于引用类型, Java 使用关键字 class 来声明类。我们看以下简单的声明一个类。
class Person {
//字段-》属性-》成员变量-->类的内部,方法的外部叫成员变量-》1.普通成员变量 2.静态成员变量
public String name;
public int age;
//方法-》行为
public void eat() {
System.out.println(name + "正在吃饭");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();//实例化对象
person.age = 10;
person.name = "bit";
//成员变量访问通过对象的引用
System.out.println(person.name);//引用类型成员变量不初始化为null
System.out.println(person.age);//int成员变量不初始化为0
person.eat();
person.sleep();
System.out.println("================");
Person person1 = new Person();
System.out.println(person1.name);
System.out.println(person1.age);
}
class为定义类的关键字,Person为类的名字,{}中为类的主体。
类中的元素称为:成员属性。类中的函数称为:成员方法。
注意事项
new 关键字用于创建一个对象的实例.
使用 . 来访问对象中的属性和方法.
同一个类可以创建对个实例。
类的成员可以包含以下:字段、方法、代码块、内部类和接口等。
class Person2 {//字段,属性,成员变量
public String name;//姓名
public int age;//年龄
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2();
System.out.println(p1.name);
System.out.println(p1.age);
}
}
注意事项
使用 . 访问对象的字段. “访问” 既包含读, 也包含写.
对于一个对象的字段如果没有显式设置初始值, 那么会被设置一个默认的初值
默认值规则
- 对于各种数字类型, 默认值为 0.
- 对于 boolean 类型, 默认值为 false.
- 对于引用类型(String, Array, 以及自定制类), 默认值为 null
认识 null
null 在 Java 中为 “空引用”, 表示不引用任何对象. 类似于 C 语言中的空指针. 如果对 null 进行 . 操作就会引发异常.
class Person2 {//字段,属性,成员变量
public String name;//姓名
public int age;//年龄
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2();
System.out.println(p1.name);
System.out.println(p1.age);
System.out.println(p1.name.length());
}
}
字段就地初始化:但是一般不这样写。
class Person2 {//字段,属性,成员变量
public String name = "Hellen";//姓名
public int age = 30;//年龄
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2();
System.out.println(p1.name);
System.out.println(p1.age);
}
}
3.2 方法 (method):用于描述一个对象的行为.
class Person2 {//字段,属性,成员变量
public String name = "Hellen";//姓名
public int age = 30;//年龄
public void introduce(){
System.out.println("我是"+ name + ",今年"+age+"岁!");
}
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2();
System.out.println(p1.name);
System.out.println(p1.age);
p1.introduce();
Person2 p2=new Person2();
p2.name="James";
p2.age=22;
p2.introduce();
}
}
方法中还有一种特殊的方法称为 构造方法 (construction method)
1、修饰属性
2、修饰方法
3、代码块(本课件中会介绍) 4、修饰类(后面讲内部类会讲到)
a) 修饰属性,Java静态属性和类相关, 和具体的实例无关. 换句话说, 同一个类的不同实例共用同一个静态属性.
class Person2 {//字段,属性,成员变量
public String name = "Hellen";//姓名
public int age = 30;//年龄
public int a;
public static int count;
public void introduce(){
System.out.println("我是"+ name + ",今年"+age+"岁!");
}
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2();
p1.a++;
Person2.count++;
System.out.println(p1.a);
System.out.println(Person2.count);
System.out.println("=============");
Person2 p2=new Person2();
p2.a++;
Person2.count++;
System.out.println(p2.a);
System.out.println(Person2.count);
}
}
b) 修饰方法
如果在任何方法上应用 static 关键字,此方法称为静态方法。
- 静态方法属于类,而不属于类的对象。
- 可以直接调用静态方法,而无需创建类的实例。
- 静态方法可以访问静态数据成员,并可以更改静态数据成员的值,但是静态方法里面不能定义静态变量
class Person2 {//字段,属性,成员变量
public String name = "Hellen";//姓名
public int age = 30;//年龄
public int a;
public static int count;
public void introduce(){
System.out.println("我是"+ name + ",今年"+age+"岁!");
}
public static void set(){
count=100;
}
}
public class TestDemo1 {
public static void main(String[] args) {
Person2.set();
System.out.println(Person2.count);
}
}
总计:
1.静态的成员变量不能在方法中定义
2.在静态方法里面不能调用普通方法,因为静态方法不依赖于对象,而普通方法依赖对象 3.在普通方法中可以调用静态方法
注意事项1:
- 静态方法和实例无关, 而是和类相关. 因此这导致了两个情况:
- 静态方法不能直接使用非静态数据成员或调用非静态方法(非静态数据成员和方法都是和实例相关的).
- this和super两个关键字不能在静态上下文中使用(this 是当前实例的引用, super是当前实例父类实例的引用, 也是和当前实例相关).
注意事项2 - 我们曾经写的方法为了简单, 都统一加上了 static. 但实际上一个方法具体要不要带 static, 都需要是情形而定.
- main 方法为 static 方法.
封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的, 只要知道如何使用类就行了.这样就降低了类使用者的学习和使用成本, 从而降低了复杂程度。
4.1 private实现封装- 被 public 修饰的成员变量或者成员方法, 可以直接被类的调用者使用.
- 被 private 修饰的成员变量或者成员方法, 不能被类的调用者直接使用。
class Person2 {//字段,属性,成员变量
private String name = "Hellen";//姓名
private int age = 30;//年龄
public void introduce(){
System.out.println("我是"+ name + ",今年"+age+"岁!");
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1=new Person2();
p1.introduce();
}
}
- 此时字段已经使用 private 来修饰. 类的调用者(main方法中)不能直接使用. 而需要借助 introduce 方法. 此时类的使用者就不必了解 Person 类的实现细节.
- 同时如果类的实现者修改了字段的名字, 类的调用者不需要做出任何修改(类的调用者根本访问不到 name, age这样的字段).
注意事项
3. private 不光能修饰字段, 也能修饰方法
4. 通常情况下我们会把字段设为 private 属性, 但是方法是否需要设为 public, 就需要视具体情形而定. 一般我们希望一个类只提供 “必要的” public 方法, 而不应该是把所有的方法都无脑设为 public.
当我们使用 private 来修饰字段的时候, 就无法直接使用这个字段了.
class Person2 {//字段,属性,成员变量
private String name = "Hellen";//姓名
private int age = 30;//年龄
public void introduce(){
System.out.println("我是"+ name + ",今年"+age+"岁!");
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1=new Person2();
p1.age=10;
p1.introduce();
}
}
此时如果需要获取或者修改这个 private 属性, 就需要使用 getter / setter 方法:
class Person2 {//字段,属性,成员变量
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1=new Person2();
p1.setName("James");
System.out.println(p1.getName());
System.out.println("=============");
p1.setAge(20);
System.out.println(p1.getAge());
}
}
注意事项
- getName 即为 getter 方法, 表示获取这个成员的值.
- setName 即为 setter 方法, 表示设置这个成员的值.
- 当set方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this, 相当于自赋值. this 表示当前实例的引用.
- 不是所有的字段都一定要提供 setter / getter 方法, 而是要根据实际情况决定提供哪种方法.
- 在 IDEA 中可以使用 alt + insert (或者 alt + F12) 快速生成 setter / getter 方法. 在 VSCode 中可以使用鼠标右键菜单 -> 源代码操作 中自动生成 setter / getter 方法.
构造方法:方法名跟类名相同,没有返回值
构造方法的作用
- 为对象分配内存
- 调用合适对象的构造方法(构造方法不止一个)
注意:
3. 如果没写构造方法,编译器自动生成一个不带参数的构造方法
4. 如果当前类有其他的构造方法,编译器就不会生成不带参数的构造方法
5. 构造方法之间可以构成重载
class Person2 {//字段,属性,成员变量
private String name;
private int age;
private String sex;
//默认构造函数 构造对象
public Person2() {
this.name = "caocao";
this.age = 10;
this.sex = "男";
}
//带有3个参数的构造函数
public Person2(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "Person2{" +
"name='" + name + ''' +
", age=" + age +
", sex='" + sex + ''' +
'}';
}
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2();
System.out.println(p1.toString());
System.out.println("================");
Person2 p2 = new Person2("James", 34, "女");
System.out.println(p2.toString());
}
}
5.2 this关键字
注意:
- this关键字表示当前对象的引用
- this.data 调用当前对象的属性
- this.fun()调用当前对象的方法
- this() 调用当前对象其他的构造方法,必须放在第一行,只能存放在构造方法中
class Person2 {//字段,属性,成员变量
private String name;
private int age;
private String sex;
//默认构造函数 构造对象
public Person2() {
//this调用构造函数
this("Hellen",22,"女");
}
//带有3个参数的构造函数
public Person2(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "Person2{" +
"name='" + name + ''' +
", age=" + age +
", sex='" + sex + ''' +
'}';
}
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2();//调用不带参数的构造方法
System.out.println(p1.toString());
}
}
我们会发现在构造函数的内部,我们可以使用this关键字,构造函数是用来构造对象的,对象还没有构造好,我们就使用了this,那this还代表当前对象吗?当然不是,this代表的是当前对象的引用。
6. 认识代码块字段的初始化方式有:
- 就地初始化
- 使用构造方法初始化
- 使用代码块初始化
前两种方式前面已经学习过了, 接下来我们介绍第三种方式, 使用代码块初始化。
使用 {} 定义的一段代码.
根据代码块定义的位置以及关键字,又可分为以下四种:
- 普通代码块
- 构造块(实例代码块)
- 静态块
- 同步代码块(后续讲解多线程部分再谈)
public class TestDemo3 {
public static void main(String[] args) {
{//直接使用{}定义,普通方法块
int x = 10;
System.out.println("x1= " + x);
}
int x = 100;
System.out.println("x2= " + x);
}
}
6.3 构造代码块
构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量
class Person3 {
private String name;//实例成员变量
private int age;
private String sex;
public Person3() {
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 TestDemo3 {
public static void main(String[] args) {
Person3 p1 = new Person3();
p1.show();
}
}
注意事项: 实例代码块优先于构造函数执行。
使用static定义的代码块。一般用于初始化静态成员属性。
class Person3 {
private String name;//实例成员变量
private int age;
private String sex;
private static int count = 0;//静态成员变量 由类共享数据 方法区
public Person3() {
System.out.println("I am Person init()!");
}
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
//静态代码块
static {
count = 10;//只能访问静态数据成员
System.out.println("I am static init()!");
}
public void show() {
System.out.println("name: " + name + " age: " + age + " sex: " + sex);
}
}
public class TestDemo3 {
public static void main(String[] args) {
Person3 p1 = new Person3();
System.out.println("============");
Person3 p2 = new Person3();
}
}
从运行结果看出,静态代码块最先执行,然后是实例代码块,最后执行构造函数,并且静态代码块只执行一次。
class Person2 {//字段,属性,成员变量
private String name;
private int age;
private String sex;
//默认构造函数 构造对象
public Person2() {
//this调用构造函数
this("Hellen", 22, "女");
}
//带有3个参数的构造函数
public Person2(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 TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2("James", 10, "女");
p1.show();
//我们发现这里打印的是一个地址的哈希值 原因:调用的是Object的toString方法
System.out.println(p1);
}
}
可以使用 toString 这样的方法来将对象自动转成字符串
class Person2 {//字段,属性,成员变量
private String name;
private int age;
private String sex;
//默认构造函数 构造对象
public Person2() {
//this调用构造函数
this("Hellen", 22, "女");
}
//带有3个参数的构造函数
public Person2(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);
}
@Override
public String toString() {
return "Person2{" +
"name='" + name + ''' +
", age=" + age +
", sex='" + sex + ''' +
'}';
}
}
public class TestDemo1 {
public static void main(String[] args) {
Person2 p1 = new Person2("James", 10, "女");
p1.show();
System.out.println(p1.toString());
}
}
注意事项:
- toString 方法会在 println 的时候被自动调用.将对象转成字符串这样的操作我们称为 序列化.
- toString 是 Object 类提供的方法, 我们自己创建的 Person 类默认继承自 Object 类, 可以 重写 toString 方法实现我们自己版本的转换字符串方法. (关于继承和重写这样的概念, 我们后面会重点介绍).
- @Override 在 Java 中称为 “注解”, 此处的 @Override 表示下面实现的 toString 方法是重写了父类的方法. 关于注解后面的课程会详细介绍.IDEA快速生成Object的toString方法快捷键:alt+f12(insert)
匿名只是表示没有名字的对象.
- 没有引用的对象称为匿名对象.
- 匿名对象只能在创建对象时使用.
- 如果一个对象只是用一次, 后面不需要用了, 可以考虑使用匿名对象
class Person3 {
private String name;//实例成员变量
private int age;
private String sex;
public void show() {
System.out.println("name: " + name + " age: " + age + " sex: " + sex);
}
public Person3(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
}
public class TestDemo3 {
public static void main(String[] args) {
new Person3("Jenny",45,"女").show();//通过匿名对象调用方法
}
}
8.重点总结
- 一个类可以产生无数的对象,类就是模板,对象就是具体的实例。
- 类中定义的属性,大概分为几类:类属性,对象属性。其中被static所修饰的数据属性称为类属性, static修饰的方法称为类方法,特点是不依赖于对象,我们只需要通过类名就可以调用其属性或者方法。
- 静态代码块优先实例代码块执行,实例代码块优先构造函数执行。
- this关键字代表的是当前对象的引用。并不是当前对象。



