类和对象

一. 类和类的实例化

1. 类

一个类可以产生无数的对象。


声明一个类就是创建一个新的数据类型,而类在Java中属于引用类型,Java使用关键字 class 来声明类。

基本语法:

//创建类
class class_name{
    field; // 成员属性
    method; //成员方法
}

//实例化对象
class_name 对象名 = new class_name();

class 为定义类的关键字,class_name 为类的名字,{}中为类的主体。
**类中的元素称为:成员属性。类中的函数称为:成员方法。

示例:

class Person {
    public int age; // 成员属性 实例变量
    public String name;
    public String sex;
    
    // 成员方法
    public void eat() {
        System.out.println("吃饭");
    }
    public void sleep() {
        System.out.println("睡觉");
    }

注意事项:

  1. 一般一个文件当中只定义一个类。
  2. main方法所在的类一般要使用public修饰。
  3. public修饰的类必须和文件名相同。
  4. 不要轻易去修改public修饰的类的名称。

2. 类的实例化

用类类型创建对象的过程,称为类的实例化。

示例:

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 Test{
    public static void main(String[] args) {
        Person person = new Person();//通过new实例化对象
        person.eat();//成员方法调用需要通过对象的引用调用
        person.sleep();
        //产生对象     实例化对象
        Person person2 = new Person();
        Person person3 = new Person();
    }
}

image.png

注意事项:

  1. new 关键字用于创建一个对象的实例。
  2. 使用.来访问对象中的属性和方法。
  3. 同一个类可以创建多个实例。

```java class Person { //普通的成员变量 都是属于对象的 private String name; private int age=19; //静态成员变量->类变量 public static int count;//0 } ``` ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22870205/1646617554878-b34f2649-c75b-475d-a86c-58bac809efe0.png#clientId=u35964f7a-01cc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=319&id=u8a031dd3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=456&originWidth=779&originalType=binary&ratio=1&rotation=0&showTitle=false&size=37566&status=done&style=none&taskId=u83e5f1ce-b863-4d42-8790-d67f7cb6ddc&title=&width=544.4957885742188)

二. 类的成员

1. 字段/属性/成员变量

**在类中,但是方法外部定义的变量。这样的变量称为“字段”或“属性”或“成员变量”。

用于描述一个类中包含了哪些数据。**

class Person {
    public String name;   // 字段
    public int age;
}
 
public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);
        System.out.println(person.age);
    }
}

image.png

使用.访问对象的字段。
**“访问”既包含读,也包含写。
**对于一个对象的字段,如果没有显式设置初始值,那么会被设置为一个默认的初始值。


> **默认值规则:** > 1. **对于简单类型,默认值为0。** > 1. **对于boolean类型,默认值为false。** > 1. **对于引用类型(String,Array,以及自定义类),默认值为 null。**

认识null

null 在Java中为“空引用”,表示不引用任何对象。类似C语言的空指针。如果对null进行操作就会引发异常。

class Person1 {
    public String name;
    public int age;
}
public class Test {
    public static void main(String[] args) {
        Person1 person = new Person1();
        System.out.println(person.name.length());   // 获取字符串长度
    }
}

image.png

字段就地初始化

很多时候我们不希望字段使用默认值,而是需要我们显式设定初始值,可以这样写:

class Person1 {
    public String name = "张三";
    public int age = 18;
}
public class Test {
    public static void main(String[] args) {
        Person1 person = new Person1();
        System.out.println(person.name);
        System.out.println(person.age);
    }
}

image.png

2. 方法(method)

用于描述一个对象的行为。

class Person1 {
    public int age = 18;
    public String name = "张三";
 
    public void show() {
        System.out.println("我叫" + name + ", 今年" + age + "岁");
    }
}
public class Test {
    public static void main(String[] args) {
        Person1 person = new Person1();
        person.show();
    }
}

image.png

方法中还有一个特殊的方法称为构造方法(construction method)在实例化对象的时候会被自动调用到的方法,方法名字和类名相同,用于对象的初始化。使用这个方法可以进行更为复杂的初始化。


> **在IDEA集成开发环境中,可以自动生成一些方法:** > 1. **get 和 set 方法:** > - **快捷键:alt + insert,选择"Getter and Setter",然后选择字段(可按ctrl进行多选)** > ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22870205/1646619210609-4f9a612a-0964-4291-a7c0-a9d8c485ae22.png#clientId=u183cc2eb-ddbf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=329&id=u0af0c857&margin=%5Bobject%20Object%5D&name=image.png&originHeight=512&originWidth=546&originalType=binary&ratio=1&rotation=0&showTitle=false&size=156404&status=done&style=none&taskId=uf1927312-935e-4cd7-b8d2-e4bdb27a2a9&title=&width=350.9915771484375) > ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22870205/1646619290497-a9551b70-3061-451a-8d4c-e3460e827621.png#clientId=u183cc2eb-ddbf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=402&id=ue79032b8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=804&originWidth=539&originalType=binary&ratio=1&rotation=0&showTitle=false&size=80641&status=done&style=none&taskId=ubfdde9de-51d9-439d-b172-cb101e85915&title=&width=269.5)![image.png](https://cdn.nlark.com/yuque/0/2022/png/22870205/1646619315662-0a8683ac-6347-404c-9246-27c8d4279bc8.png#clientId=u183cc2eb-ddbf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=309&id=ud2e9819a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=481&originWidth=546&originalType=binary&ratio=1&rotation=0&showTitle=false&size=276710&status=done&style=none&taskId=u02ef91ef-8f87-45bb-a3f4-d4ae4d53193&title=&width=350.9999694824219) > 2. **显示字段的方法:** > - **快捷键:alt + insert,选择"toString',再选择字段。(跟上面的方法差不多)** > ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22870205/1646619426439-27686369-62db-4afe-8e7d-c51f1a24255c.png#clientId=u183cc2eb-ddbf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=199&id=u57139240&margin=%5Bobject%20Object%5D&name=image.png&originHeight=337&originWidth=808&originalType=binary&ratio=1&rotation=0&showTitle=false&size=262473&status=done&style=none&taskId=u25d1e358-222c-48dd-b0d3-b14ff9a989b&title=&width=476.9915771484375) > **在调用的时候,直接在**`System._out_.println();`**实例成员,然后自动调用上面自动生成的toString方法:** > ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22870205/1646619531738-cfc4d230-c245-418c-9d57-38c63fad5df6.png#clientId=u183cc2eb-ddbf-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=126&id=ued49e1c6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=192&originWidth=695&originalType=binary&ratio=1&rotation=0&showTitle=false&size=150934&status=done&style=none&taskId=u298e7eb5-6346-42e2-94c3-9f04de8ba54&title=&width=457.49578857421875) > **注意:** > 1. **这个方法是重新实现了 Object类的 toString()方法。** > 1. **Object 是所有类的父类。** > 1. **@Overrride 是注解,这个注解代表的是这个方法是重写的。**
## 3. static关键字 > 1. **修饰属性** > 1. **修饰方法** > 1. **代码块** > 1. **修饰类**
> **a ) 修饰属性** > **Java静态属性和类相关,和具体的实例无关。也就是说同一个类的不同实例共用的是同一个静态属性。**
class TestDemo{
    public int a;
    public static int count;
}

public class Test{
 
    public static void main(String[] args) {
        TestDemo t1 = new TestDemo();
        t1.a++;
        TestDemo.count++;
        System.out.println(t1.a);
        System.out.println(TestDemo.count);
        System.out.println("============");
        TestDemo t2 = new TestDemo();
        t2.a++;
        TestDemo.count++;
        System.out.println(t2.a);
        System.out.println(TestDemo.count);
    }
}

image.png

count被static所修饰,所有类共享。且不属于对象,访问方式为:类名.属性

image.png

b ) 修饰方法
如果在任何方法上使用 static 关键字,此方法称为静态方法。
****静态方法属于类,而不属于类的对象。

可以直接调用静态方法,而无需创建类的实例。**

**静态方法可以访问静态数据成员,并可以更改静态数据成员的值。

class Person {
    public String name;
    public int age = 18;
    public static int size; 

    public void fun1() {
        int a = 10; // 局部变量,存储在栈中
        fun2(); // 非静态方法 可以 调用静态方法
        System.out.println("这是非静态的方法");
    }

    // 静态成员方法
    public static void fun2() {
        // age = 99; error 静态方法内部 不能 访问非静态的数据成员
        size = 1000;
        // func1(); 静态方法 不能 调用非静态方法
        System.out.println("这是静态的方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        // 如何访问静态的类方法:类名.方法名()
        Person.fun2();

        // 注意此main是静态的,就像上述所说,静态方法不能调用非静态方法
        // 非要调用只能像这样:通过引用来调用
        Person per2 = new Person();
        per2.fun1();
    }
}

image.png

注意事项1:

  1. 静态方法不能直接使用非静态数据成员或调用非静态方法(非静态数据成员和方法都是和实例相关的)。
  2. this 和 super 两个关键字不能在静态上下文中使用(this 是当前实例的引用,super是当前实例父类实例的引用,也是和实例相关的)。

注意事项2:
我们曾经写的方法为了简单,都统一加上了 static,但实际上一个方法具体要不要带 static,都需要依据情形而定。main方法为 static 方法。

三. 封装

在我们写代码的时候经常会涉及两种角色:类的实现者 和 类的调用者。
**封装的本质:就是让类的调用者不比太多的了解类的实现者是如何实现类的,只要知道如何使用类就行。

1. private 实现封装

**private / public 这两个关键字表示“访问权限控制”。

被 public 修饰的成员变量或者成员方法,可以直接被类的调用者使用。**

**被 private 修饰的成员变量或者成员方法,不能被类的调用者使用。

直接使用 public

class Person {
    public String name = "张三";
    public int age = 18;
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println("我叫" + person.name + ", 今年" + person.age + "岁");
    }
}

这样的代码导致类的使用者(main方法的代码)必须要了解Person类内部的实现,才能够使用这个类。学习成本较高,一旦类的实现者修改了代码(例如,把 name 改为 myName),那么类的使用者就需要大规模的修改自己的代码,维护成本较高。

class Person3 {
    private String name = "张三";
    private int age = 18;
 
    public void show() {
        System.out.println("我叫" + name + ", 今年" + age + "岁");
    }
}

public class Test {
    public static void main(String[] args) {
        Person3 person = new Person3();
        person.show();
    }
} 

image.png

此字段已经使用 private 来修饰,类的调用这(main方法中)不能直接使用,而需借助 show 方法,此时类的使用者就不必了解Person类的实现细节。
**同时如果类的实现者修改了字段的名字,类的调用者不需要做出任何修改(类的调用者根本访问不到由 private 修饰的字段。


## 2. getter 和 setter 方法 **当我们使用 private 来修饰字段的时候,就无法直接使用这个字段了。我们可以通过访问getter方法和setter方法来获取和设置成员的值。**
![image.png](https://cdn.nlark.com/yuque/0/2022/png/22870205/1646633737471-084fd2dc-a90e-4bec-8a02-bb8586b9f215.png#clientId=u1136ed2c-2486-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=361&id=u416825c9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=475&originWidth=590&originalType=binary&ratio=1&rotation=0&showTitle=false&size=294945&status=done&style=none&taskId=u482284d6-f9ec-40c0-b897-63faf782d08&title=&width=447.99578857421875) > **当 set 方法的形参名字和类中的成员属性的名字一样的时候,如果不适应this,则相当于自己给自己赋值,this表示当前实例的引用。**

在IDEA中可以通过 alt + insert 来设置方法,具体参照上述第二章节“方法(method)”

四. 构造方法

1. 基本语法

构造方法是一种特殊的方法,使用关键字 new 实例化新对象时就会被自动调用,用于完成初始化操作。

new 的执行过程:

  1. 为对象分配内存空间。
  2. 调用对象的构造方法。

语法规则:

  1. 方法名必须与类名相同。
  2. 构造方法没有返回值类型声明。
  3. 每一个类中一定至少存在一个构造方法(没有明确定义,则西苑会自动生成一个无参构造方法)

注意事项:

如果类中没有提供任何的构造函数,那么编译器会默认生成一个不带有参数的构造函数。
若类中定义了构造方法,则默认的无参构造将不再生成。
构造方法支持重载,规则和普通方法的重载一样。

示例:

class Person4 {

    private String name;//实例成员变量
    private int age;
    private String sex;
    //默认构造函数 构造对象
    public Person4() {
        this.name = "caocao";
        this.age = 10;
        this.sex = "男";
    }
    //带有3个参数的构造函数
    public Person4(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);
    }

}
class Test{
    public static void main(String[] args) {
        Person4 p1 = new Person4();//调用不带参数的构造函数 如果程序没有提供会调用不带参数的构造函数
        p1.show();
        Person4 p2 = new Person4("zhangfei",80,"男");//调用带有3个参数的构造函数
        p2.show();
    }
}

image.png

2. this关键字

this表示当前对象引用(注意不是当前对象),可以借助 this 来访问对象的字段和方法。

class Person2 {
    private String name;
    private int age;
    private static int count;

    public Person2() {
        // this调用其他构造方法来简化代码
        this("caocao",18); // 只能放在第一行,否则报错
        // this("zhangfei"); 只能调用一个
        System.out.println("Person2<init>");
        // this("caocao",18);不在第一行则报错
    }

    // 可以使用alt + insert自动生成
    public Person2(String Name,int Age) {
        this.name = Name;
        this.age = Age;
        System.out.println("Person2<String,int>");
    }

    public Person2(String Name) {

    }


public class Demo3 {
    public static void main(String[] args) {
        Person2 per = new Person2();
    }
}

image.png

我们会发现在构造函数内部,我们可以使用this关键字,构造函数是用来构造对象的,对象还没有构造好,我们就是使用了this,那this还代表当前对象吗?
当然不是,this代表的是当前对象的引用。


# 五. 认识代码块 **代码块的分类有三种:** > 1. **实例代码块** > 1. **静态代码块** > 1. **本地代码块**
class Person2 {
    private String name;
    private int age;
    private static int count;

    public Person2() {
        System.out.println("Person2<init>");
    }

    public Person2(String Name,int Age) {
        this.name = Name;
        this.age = Age;
        System.out.println("Person2<String,int>");
        
        //本地代码块,没啥用
        {
            System.out.println("本地代码块.......");
        }
    }

    // 实例代码块,不过没啥用,了解即可
    {
        this.name = "zhangfei ";
        count = 99;
        System.out.println("实例代码块........");
    }

    // 静态代码块
    static {
        // this.name = "zhangsan"; 不能访问非静态的数据成员
        // count = 100;
        System.out.println("静态代码块.......");
    }
}

public class Demo3 {
    public static void main(String[] args) {
        Person2 per = new Person2();
        System.out.println("================");
        Person2 per2 = new Person2();
        // 重要:静态的内容只会被执行一次,且最早被执行的。
    }
}

image.png

注意事项:
静态代码块不管生成多少个对象,期间只会执行一次,且是最先被执行的。
**静态代码块执行完毕后,实例代码块执行,再然后是构造函数执行。
**如果还有静态成员变量,则是谁先定义谁先执行,如:

class Person {
    public static int count = 0;
    
    static {
        count = 99;
    }
}

则先执行第二行代码,然后执行第4行代码,最终count为99。

六. 匿名对象

**没有引用的对象称为匿名对象。

匿名对象只能在创建对象时使用。**

**如果一个对象只是用一次,以后都不需要了,可以使用匿名对象。

class Person4 {

    private String name;//实例成员变量
    private int age;
    private String sex;
    //默认构造函数 构造对象
    public Person4() {
        this.name = "caocao";
        this.age = 10;
        this.sex = "男";
    }
    //带有3个参数的构造函数
    public Person4(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);
    }

}
class Test{
    public static void main(String[] args) {
        new Person4("caocao",19,"男").show(); // 通过匿名对象调用方法
    }
}

image.png

七. 面向对象

posted @   interestinmachine  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示