【JavaSE】(4)类和对象

目录

一、面向对象

1. 面向过程

2. 面向对象

3. 类和对象

二、类

1. 简述

2. 示例代码

三、对象

1. 创建对象

2. 使用对象

3. 所使用内存空间示意图

4. new 一个对象发生的事

四、当前对象的引用:this

1. 没有 this 存在的问题

2. this 引用的作用

五、构造方法

1. 构造方法的作用与定义

2. 示例

3. 成员变量的初始化

4. 构造函数自动生成

六、封装

1. 含义及作用

2. 自动生成访问成员变量的成员方法

3. 访问限定符

七、包

1. 作用

2. import

3. import static

4. 自定义包

5. package

八、static

1. static 的含义即作用

2. 注意事项

3. 静态成员变量的初始化

九、代码块

1、局部代码块(普通代码块)   

2、静态代码块

3、实例代码块(构造代码块)

4、示例代码

5、总结

十、对象的打印


一、面向对象

1. 面向过程

        面向过程,注重于完成任务的详细步骤,比如手洗衣服:拿盆->放水->放衣服->放洗衣粉......。

2. 面向对象

        面向对象,注重于完成任务所需的对象,比如洗衣机洗衣服:人、衣服、洗衣粉、洗衣机,人放洗衣粉和衣服到洗衣机->从洗衣机取出衣服。

3. 类和对象

        类:描述一类事物,比如人。

        对象:一个具体的事物(实体),比如小许同学。

二、类

1. 简述

        类包含成员变量(体现事物的属性)、成员方法(体现事物的功能、行为)。比如学生,属性有:姓名、年龄、性别、学校、年级......,行为有:在吃饭、在上课、在考试、在散步、在睡觉、在学习......

2. 示例代码

        写一个学生类:(属性定义在类里,方法外)

public class Student {
    public String name;
    public char sex;
    public int age;
    public double score;

    public void doClass(){
        System.out.println("在上课......");
    }

    public void doExam(){
        System.out.println("在考试......");
    }

    public void doRelax(){
        System.out.println("在休息......");
    }

    public void showInfo(){
        System.out.println("姓名:" + name + " 性别:" + sex + " 年龄:" + age + " 成绩:" + score);
    }
}

注:

  • 成员变量和成员方法都有静态和非静态之分,用修饰符 static 区别,这里统一不写 static、写 public,后面深入学习。
  • 建议一个文件一个类。
  • 成员变量有默认值,与数组的默认值相同,因此不初始化也能使用。

三、对象

1. 创建对象

        创建对象的过程就是类的实例化,用new。可以在同一包(src)中的另一个文件的类中的 main方法里创建对象,也可以在本类的 main 方法里。

        示例代码:

public class Demo {
    public static void main(String[] args) {
        Student student = new Student(); // 创建对象
    }
}

2. 使用对象

        用 . 访问对象的成员变量和成员方法。

        示例代码:

public class Demo {
    public static void main(String[] args) {
        Student student = new Student(); // 创建对象
        // 访问成员变量
        student.name = "小许";
        student.sex = '女';
        student.age = 23;
        student.score = 99.5;
        // 访问成员方法
        student.showInfo();
        student.doRelax();
    }
}

3b39fb22371f41d9861e373a75683bca.png

3. 所使用内存空间示意图

40fb375a958d4c8b8266b3e49b1b95d3.png

        使用对象的成员方法的过程,不会占用堆,而是占用 JVM 栈。

4. new 一个对象发生的事

        加载对象的类。(编译后的字节码,要加载到 JVM 中)->

        给对象开辟内存空间。->

        处理并发安全,如:多个线程同时给对象开辟同一个内存空间,通过一些策略解决。->

        初始化内存空间,如:成员变量设默认值。->

        给对象加头信息。->

        调用构造函数。

四、当前对象的引用:this

1. 没有 this 存在的问题

        (1)当成员变量和成员方法的形参重名,分不清变量是成员变量还是形参:

d9fef2feb7bf4b62ad9d21e04e8b9957.png

3c95927d39324d43a2654563f78b39d3.png

d1349b42578d470994c96b86ae6fa76a.png

        实际上,局部变量优先级更高,结果为形参自己给自己赋值,而成员变量依然为默认值。

        (2)成员方法不知道调用它的对象是谁(形参里面并没有对象的引用)

2. this 引用的作用

  • 访问当前对象的成员变量

e508fd7249844ea5824cb4fd20dddfda.png

  • 访问当前对象的成员方法。(静态成员方法不能用 this,为什么后面再学)

        this 只能在成员方法中使用,this 是成员方法的第一个隐藏参数,表示当前对象的引用,编译后会把隐藏的参数加上去,类似这样:

667fb692035142caa754acaf61ee55f0.png

        验证,this 就是引用变量 student:

72e62396f21d415998edb8845c57d504.png

d45561ed50154f7da797de8497a54ac0.png

682871ca5e974d61b796ab97b53e943b.png

  • this() 调用当前对象的其它构造方法(看下一章的示例)。

五、构造方法

1. 构造方法的作用与定义

        构造方法,名字与类名相同没有返回值,作用就是初始化成员变量

        创建对象后,编译器会自动调用构造方法,并只调用一次。在没有定义构造方法时,编译器会默认定义一个什么也不做的构造方法。但是定义了构造方法后编译器就不会定义默认的构造方法了。

        可以重载

2. 示例

1a733ce2ce914b95a5c065c129ce2727.png

49f60cc76b444337a42cde0b87620c62.png

37c42ac6b3e241ee994e1db9d15101a5.png

        构造函数里,this() 调用其他构造函数,简化代码

33af925f365d433fa1c2c4a1c6d60fad.png

        注:this() 只能在构造方法内的第一行。不能用 this() 互相调用,会产生递归。

3. 成员变量的初始化

(1)默认初始化

(2)就地初始化:在类里声明成员变量的时候就初始化。

5cdbbbada20543dc9a0153e4c72efa80.png

(3)用构造方法初始化

注:同时有就地、构造函数初始化,先就地,再构造函数初始化,会覆盖。

4. 构造函数自动生成

        集成开发环境提供了自动生成构造函数的方法:在要生成的位置,右击,generate,constructor,ctrl+选中字段。

ee1e8df8216e4e60b4bf9dc333a3b133.png

e5d499c87624439090117a1e932107b0.png

5、例题

(1) 不是构造方法,而是一个普通的成员方法,答案选 C 。

六、封装

1. 含义及作用

        封装就是只提供成员方法接口,而不提供实现的细节和成员变量。如:我们使用电脑的接口、按钮,而不能看到内部的零件。

        ① 方便管理代码:如果对象直接调用成员变量修改值,某次类中的成员变量名修改了,那么调用它的对象都需要修改调用成员变量名,非常麻烦。

        ② 增强安全性:只提供指定方法,比如:银行存取钱,不可能让你修改金额(成员变量),只允许你查询(只提供查询的成员方法)。

        隐藏(private)成员变量提供访问成员变量的方法,就算类里成员变量名修改了,也不会对使用者造成影响

        示例代码:

49f2f20c90594c76857cfe3e74cf3b3c.png

f7fa2c66825848f5b6245429c78f3aa8.png

2. 自动生成访问成员变量的成员方法

7cabb2348ffb4d5ab1d10154db244617.png

3. 访问限定符

访问限定符
范围privatedefaultprotectedpublic
同一个类
同一个包的不同类
不同包的子类
不同包的非子类
  • 修饰成员变量、成员方法。
  • 修饰类:只有 public 和 default
  • default 的形式是没有修饰符。

七、包

1. 作用

        包就是把多个类分类,方便管理类。不同包中的类可以重名。

2. import

        使用 Arrays 类要导类:

7cda5a423fa442399933ae11a2d9457e.png

        两种导类形式:

898acfebbf6d4ac3958a4efc3f8bc0dd.png

        * 是通配符,里面的类都可以用,但是用到的才会加载对应的类,没用到不会加载。

        推荐使用第一种避免不同包中,存在同名类的冲突。如:使用 Date 类,想用 java.sql 包中的 Data 类,但是 java.util 也有 Date 类:

17bac4434a5c4e18a99f6ed8eba1297c.png

aa0b8aa523294d1c92e3bbcdc233e30d.png

         就不清楚加载哪个包中的类。要么使用完整类名:

1cab50a70e354202ac3d58c8cdeaebc8.png

3. import static

        导入包中的静态成员变量和方法:

caf0dfe759884d319c4fa75cbb81518e.png

5c415fbb5df04278a4b79a601698431c.png

4. 自定义包

199a458ae027459086a6188967b622b0.png

        包名一般是公司的域名,建成后包名会倒着来,不合并中间包名,显示包结构:

56642e5144b14d11a2ecc132e57875e9.png

ad49ee8d925448b7938e29a186fd7b1c.png

5. package

        声明该文件代码在哪个包。

49628123223e498f8f2be227e3b1d599.png

        如果文件没有 package,那么在默认包里。

933d3248d3314a83ac83a66a2682627f.png

6、java.lang

        java.lang 很特殊,它包含 java 的基础类,像 String、Exception、Math 类等都在其中。它不需要 import 就能使用其中的类

八、static

1. static 的含义即作用

        修饰静态成员变量、方法,表示属于类,而不是属于某个对象存储于方法区。可以用某个对象调用静态成员,但不推荐,推荐用类名调用静态成员。

        static 能使所有的对象共用同一个内容相同的成员变量,而不必重复占用堆空间,如6班的同学共用 class6。

2. 注意事项

  • 静态成员随着类的加载而创建,随类的卸载而销毁(生命周期与类一致)。
  • Java 当中不允许定义局部的静态变量。局部变量,生命周期在方法内;静态变量,生命周期在类内,两者冲突。
  • 静态成员方法中,不能使用非静态成员。(因为不属于某个对象,即没有对象)
  • 静态成员方法,不能重写。(后续学习)

3. 静态成员变量的初始化

        静态成员变量一般不在构造函数中初始化。有两种初始化方式:

  • 就地初始化
  • 静态代码块初始化。(看下一节)

九、代码块

        代码块就是用 {} 括起来的部分。

1、局部代码块(普通代码块)   

        局部代码块就是在方法里面的代码块。不常用,尽量不用。    

ebca02274bee44caa6136c168985e1b4.png

2、静态代码块

        一般用于初始化静态成员变量

3、实例代码块(构造代码块)

        一般用于初始化实例成员变量

      同步代码块。(后续学习)

4、示例代码

dc3fb3aa785041d084990aa1faa3d609.png

97d82c2845bd43e89670ef5fd44ce841.png

c234e85639b54595a2a742edca376169.png

5、总结

        执行顺序(不同):静态代码块、静态成员变量(类加载时就分配内存初始化)->实例代码块、实例成员变量(创建对象时)->构造方法

        执行顺序(相同):依次。

        不管 new 了多少个对象,静态代码块只执行一次

        多个静态代码块,会合并执行。

        同样,静态代码块不依赖于对象,因此没有对象,也执行。

8b50a4f38b7d4c28a022e70b9ba4399b.png

d5b7f7ca1800471399357fce1aa2b705.png

十、内部类

        一个事物的内部,有个部分需要一个完整的结构描述,但这个完整结构又只为外部服务,就可以设计成内部类。

        内部类分为:静态内部类、实例内部类、匿名内部类(最常用)、局部内部类(基本不用)。

1、静态内部类

        处在跟成员变量一样的位置,加 static

public class OuterClass {
    public int data1 = 1;
    private int data2 = 2;
    public static int data3 = 3;

    public void test() {
        System.out.println("out::test方法");
    }

    //静态内部类
    static class InnerClass {
        public int data4 = 4;
        public static int data5 = 5;

        public void func() {
            System.out.println("InnerClass::func()");
            OuterClass outerClass = new OuterClass();
            System.out.println(outerClass.data1);
            System.out.println(outerClass.data2);
            System.out.println(data3);
            System.out.println(data4);
            System.out.println(data5);
        }
    }
}

        静态内部类,不依赖外部类的对象因此

  • 创建静态内部类对象,不需要先创建外部类对象

  • 静态内部类不能访问外部类非静态成员

  • 字节码名称包含:外部类名+内部类名

2、实例内部类

        去掉 static,JDK8不支持在实例内部类中定义静态成员变量

public class OuterClass {
    public int data1 = 1;
    private int data2 = 2;
    public static int data3 = 3;

    public void test() {
        System.out.println("out::test方法");
    }

    //实例内部类
    class InnerClass {
        public int data1 = 99;
        public int data4 = 4;

        public void func() {
            System.out.println("InnerClass::func()");
            System.out.println(data1);
            System.out.println(data2);
            System.out.println(data3);
            System.out.println(data4);
        }
    }
}

       内部类能直接访问外部类成员,但外部类不能直接访问内部类成员。

        创建实例内部类对象,先实例化外部类通过外部类的实例,实例化内部类

        如果外部类和内部类存在相同的成员变量data1,默认情况下访问的是内部类的data1

         如果外部类和内部类存在相同的成员变量data1,想访问外部类的data1,则:

  • 通过外部类对象,访问data1:

  • 通过外部类名.this访问data1:

3、匿名内部类

        匿名内部类,相当于继承或者实现外部类或接口,重写方法。匿名内部类有两种形式:

(更正:上图中的 Outer 改为 OuterClass)

或者:

        运行结果,执行内部类重写的方法:

4、局部内部类

        定义在方法内,作用域只在方法内,即只能在方法内使用,当然就不能被 public、static 修饰了。

5、私有 “失效” 现象

情况1:内部类可访问外部类私有属性。

        原因:编译器会在外部类中自动生成提供私有属性的静态方法(即acess$0,access$1等)。

情况2:外部类可访问内部类私有成员和构造方法。

        原因:编译器会在内部类中自动生成提供私有属性的静态方法。

参考博客:细话Java:"失效"的private修饰符 - 技术小黑屋

十一、对象的打印

        ① 自己写一个方法:

0f0806d38261445db902079a6ceebee9.png

        ② 直接用 System.out.println 打印(不是想要的结果):

23db423dcf3748f5b86686427f01dbe5.png

b8ca7955f7c4421f9220004134979bd5.png

        查看 println 底层:

b3517c26702a4d54906a2cc91abb4ca5.png

a65c35dae0034dbe884c5893dd94875e.png

cc9ab72cf8924baf9d83b0add19eef17.png

        重写 toString(可以自动生成):

5c57c5afcd09495bad07fdad9c09c7e7.png

f8dc22e2e655490fbd9f602f8a1048c8.png

7a90eaf378764445ae0387c7671983f5.png

十二、用类解决在函数中更改外部基本数据类型值的问题

        对象的引用可以更改函数外部对象的值。那么可以在类中定义基本数据类型成员,通过引用来改变对象的成员变量的值。

        示例代码:

class Test {
    private int data;

    public Test(int data) {
        this.data = data;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }
}

public class Main{
    public static void swap(Test a, Test b){
        int temp;
        temp = a.getData();
        a.setData(b.getData());
        b.setData(temp);
    }

    public static void main(String[] args) {
        Test a = new Test(10);
        Test b = new Test(20);
        swap(a, b);
        System.out.println(a.getData());
        System.out.println(b.getData());
    }
}

        运行结果:交换成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值