Java中的类和对象


一、类和对象的初步认识

1.1 类和对象的基本概念

我们知道,在Java中一切皆对象。
那什么是类?什么是对象呢?
类就是一类对象的统称。对象就是这一类具体化的一个实例.
举个简单的例子:我们观察林丹和张继科,发现他们都具有一些相同的属性:都有鼻子眼镜嘴巴等,都具备相同的行为:吃喝拉撒睡。于是我们把具有相同属性和行为的一类对象抽象为类,使用类来描述这类对象的特性。
类是一个抽象的概念,人类,猫类,犬类,它无法具体到某个实体。
对象是某个类的一个实体,比如张三就是人类的一个实体,柯基是犬类的一个实体,由同一个类实例出来的对象具有不同的属性值和行为。

1.2 类和类的实例化

基本语法:

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

class People{
    //成员属性
    String name;
    int age;
    String sex;
    //成员方法
    void show(){
        System.out.println("name = " +name+",age = "+age+",sex = "+sex);
    }
}

注意
1.类的命名使用有意义的大驼峰单词命名方式:
从第一个单词开始首字母就大写,多个单词都是首字母大写。
2.类中的成员变量都有默认值。

类的实例化:

<class_name> <对象名> = new <class_name>();

public class TestDemo {
    public static void main(String[] args) {
        //实例化对象
        People p = new People();
    }
}

当产生一个对象后,我们可以用"引用."来访问对象的属性和方法。
在这里插入图片描述
成员变量可以在定义时赋初始值,成员变量就地初始化:
在这里插入图片描述注意:
在这里插入图片描述

二、面向对象的封装性

2.1 封装的基本概念及用法

面向对象一共有三大特性:封装,继承和多态

封装:保护性和易用性(封装就有很多种表现形式)
private实现属性和方法的封装只是封装的一种。

我们为什么要对属性和方法进行封装呢?
拿银行卡这个类来说,对于银行卡的卡号,余额,密码这三个属性,如果这三个属性直接暴露在外部,直接就在卡片上贴着,谁都能看见,这是非常不合理的,不能让这些属性通过对象直接就能访问。
再比如,对于汽车这个类来说,车真正发动起来,是需要很多个属性间的相互配合,这些属性对于用户来说,是不可见的,也是用户不关注的,对用户来说,只需要按一键启动来启动汽车,在方法的内部对这些属性进行调配和操作,用户不需要了解汽车内部的属性。

在Java中,所谓的权限修饰符,指的是,你修饰的属性,方法,类,到底可见的范围有多大,一共有四大访问修饰符,可见的范围由小到大依次为:
private < default(不要写这个关键字,啥权限也没有就是default) < protected < public

private:私有的,被private修饰的属性和方法,只在当前类的内部可见,出了类的{},对外部就完全隐藏了,外部不知道有其存在。
public:公共的,公开的,被public修饰的东西,在当前程序(项目)中都是可见的,都是可以使用的。

关于private的可见范围:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 getter和setter方法

要想在类的外部去使用这些私有属性,需要使用类提供的getter(取值)和setter(修改值)
到底哪些属性需要提供getter,让外部可见,哪些属性需要提供setter,让外部修改,都要根据这个属性的特征来决定。
在这里插入图片描述
在这里插入图片描述

private关键字能否修饰一个类?

private关键字不能修饰外部类。
类定义出来就是用来产生对象,让外部使用,private修饰一个类,定义之后外部不可用,无法使用。

三、构造方法

3.1 基本语法

构造方法是类中非常特殊的一类方法,使用关键字new实例化对象时,实际上调用的就是该类的构造方法。

构造方法的作用就是产生对象

构造方法语法规则:
1.方法的名称与类名称完全相同
2.构造方法没有返回值声明(不是void)
3.一个类中至少存在一个构造方法,若没有显示定义,编译器会生成一个默认的无参构造
在这里插入图片描述在这里插入图片描述

当类中自定义了构造方法,则默认的无参构造就不再生成。

在这里插入图片描述

3.2 new执行过程

使用关键字new产生一个对象时,大致分为一下两步:
1.为对象在队中分配空间
2.调用对象的构造方法为对象成员变量赋值。

下面来分析一下代码的执行过程:

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
    }
}
class Person {
    private String name;
    private int age;
    public Person() {
        //name = null;age = 0;
        System.out.println("Person的无参构造。");
    }
}

当调用new person(),其实就是产生了一个Person对象
首先在堆上开辟一块内存空间(大小由该类中成员变量的属性决定)
调用对象的构造方法为所有成员变量赋值
当构造方法调用结束,该对象就初始化完成。
在这里插入图片描述

3.3 构造方法的重载

构造方法可以重载,构造方法是为了类中的成员变量赋值的,此时的重载只可能是参数的个数不同。

为啥此时的重载只能是参数个数不同,和类型无关呢?
构造方法是为成员变量赋值,而成员变量的类型在类定义时就指定好了,只是初始化的变量个数不同。

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        Person person1 = new Person("铭哥");
        Person person2 = new Person("铭哥",18);
        // 这三个对象构造方法都已经调用结束,初始化完成
    }
}

class Person {
    private String name;
    private int age;
    private String sex ;
    public Person() {
        // name = null,age = 0,sex = null
        System.out.println("Person的无参构造。");
    }
    public Person(String n) {
        // name = null,age = 0,sex = null
        name = n;
        System.out.println("name = " + name);
        System.out.println("Person的一个参数的有参构造");
    }
    public Person(String n,int a) {
        // name = null,age = 0,sex = null
        name = n;
        age = a;
        System.out.println("name = " + name + ",age = " + age);
        System.out.println("Person的两个个参数的有参构造");
    }
}
//运行结果
Person的无参构造。
name = 铭哥
Person的一个参数的有参构造
name = 铭哥,age = 18
Person的两个个参数的有参构造

在这里插入图片描述

能否通过实例化对象调用构造方法?
person.Person();

不能调用,对象就是由构造方法产生的,自己又在调用产生自己的构造方法,这是不合理的。
JVM产生对象调用构造方法,对象实例化结束,无法在程序中手动调用构造方法再次实例化对象。

在成员变量定义时就赋初值,程序如何运行?

成员变量在构造方法中完成赋值。
在这里插入图片描述

四、this关键字

this表示当前对象的引用

在这里插入图片描述

4.1 调用当前对象的成员变量

下面来看一段代码:

public class ThisTest {
    public static void main(String[] args) {
        Student stu1 = new Student("张三",18,"男");
        stu1.show();
    }
}

class Student {
    private String name;
    private int age;
    private String sex;

    public Student(String name,int age,String sex) {
        name = name;
        age = age;
        sex = sex;
        System.out.println("Student类的有参构造");
    }
    public void show() {
        System.out.println("name = " + name + ",age = " + age + ",sex = " + sex);
    }
}
//运行结果
Student类的有参构造
name = null,age = 0,sex = null

我们发现,当调用有参构造方法时,类中的成员变量并未被赋值,这是为什么呢?
我们知道,构造方法中的三个参数都是形参,这三个参数此时正好与成员变量同名。程序遵循就近匹配原则,编译器会找最近的相同名称的变量。就相当于形参自己指向自己,对类中的成员变量没有任何影响。
在这里插入图片描述
如何打破就近匹配原则,从类中找成员变量呢?
我们使用this变量

public class ThisTest {
    public static void main(String[] args) {
        Student stu1 = new Student("张三",18,"男");
        stu1.show();
    }
}

class Student {
    private String name;
    private int age;
    private String sex;

    public Student(String name,int age,String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        System.out.println("Student类的有参构造");
    }
    public void show() {
        System.out.println("name = " + name + ",age = " + age + ",sex = " + sex);
    }
}
//运行结果
Student类的有参构造
name = 张三,age = 18,sex =

4.2 this调用类中的方法

1. this调用类中的成员方法

在这里插入图片描述

2.this调用构造方法

在这里插入图片描述
若不同参数的构造方法之间出现了重复的调用,可以使用this(参数)调用其他的构造方法。
在这里插入图片描述
注意:

this调用其他的构造方法必须放在当前构造方法的首行

在这里插入图片描述

this调用构造方法不能成“环”

一下代码中,第一个无参构造方法调用了第二个有参构造,第二个有参构造又调用了第一个无参构造,会形成死循环。
在这里插入图片描述

3.this表示当前对象的引用

this就相当于一面镜子,我当前是通过哪个对象调用的属性或者方法,this就代表谁。当用stu1调用this的时候,this表示的就是stu1这个对象,打印出来的就是stu1的地址。

public class ThisTest {
    public static void main(String[] args) {
        Student stu1 = new Student();
        System.out.println(stu1);
        stu1.whoAmI();
        System.out.println("-------------------------------");
        Student stu2 = new Student();
        System.out.println(stu2);
        stu2.whoAmI();
    }
}
class Student {
    private String name;
    private int age;
    private String sex;
    public void whoAmI() {
        System.out.println(this);
    }
}
//运行结果
Student@4554617c
Student@4554617c
-------------------------------
Student@74a14482
Student@74a14482

五、代码块

代码块:就是使用{}括起来的一段代码。

5.1 普通代码块

定义在方法中,用{}括起来的代码块。

public class CodeTest {
    public static void main(String[] args) {
        {
            //普通代码块,出了大括号就不认识
            int a = 10;
        }
        int a = 20;
        System.out.println(a);
    }
}
//运行结果
20

5.2 成员代码块

定义在类中,使用{}括起来的代码块,也叫构造块。

public class CodeTest {
    public static void main(String[] args) {
        Animal animal = new Animal();
        Animal animal2 = new Animal();
    }
}
class Animal {
    private String name;
    {
        // 构造块
        System.out.println("2.Animal的构造块");
    }
    public Animal() {
        System.out.println("1.Animal的无参构造");
    }
}
//运行结果
2.Animal的构造块
1.Animal的无参构造
2.Animal的构造块
1.Animal的无参构造

构造块直接定义在类中,不加任何修饰符,它优先于构造方法执行,有几个对象产生就调用几次构造块。

5.3 静态代码块

定义在类中,使用static修饰的代码块,在类加载的时候执行一次

public class CodeTest {
    public static void main(String[] args) {
        Animal animal1 = new Animal("小狗");
        Animal animal2 = new Animal();
    }
}
class Animal {
    private String name;
    static {
        // 静态块
        System.out.println("3.Animal的静态代码块");
    }
    {
        // 构造块
        System.out.println("2.Animal的构造块");
    }
    public Animal() {
        System.out.println("1.Animal的无参构造");
    }
    public Animal(String name) {
        this.name = name;
        System.out.println("1.Animal的有参构造");
    }

}
//运行结果
3.Animal的静态代码块
2.Animal的构造块
1.Animal的有参构造
2.Animal的构造块
1.Animal的无参构造

静态代码块在类加载的时候执行一次,与对象无关,无论产生多少对象,静态代码块只在类加载的时候执行一次。

主类中的静态代码块优先于主方法执行
在这里插入图片描述

主类中的静态代码块优先于主方法执行,JVM要执行主方法,首先得加载主类,主类一加载,静态块就执行了。

在这里插入图片描述

  • 21
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值