Java-类和对象

Posted ViolentAsteroid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-类和对象相关的知识,希望对你有一定的参考价值。

目录

一.类和对象的初步认知

1.面向过程和面向对象

2.面向对象设计

二.类和类的实例化

1.什么是类

2.类的实例化

三.类的成员

1.成员变量

2.方法

3.static关键字

静态成员变量

静态成员变量储存方式

静态成员方法

总结-必看!!!

4.toString方法

5.匿名对象

四.封装

1.private实现封装

2.getter和setter方法

五.构造方法

1.基本语法

2.this关键字

六.代码块

1.什么是代码块

2.本地代码块

3.实例代码块

4.静态代码块 


  

一.类和对象的初步认知

1.面向过程和面向对象

面向过程:C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题

面向对象:JAVA是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成 

面向过程:注重的是过程,在整个过程中所涉及的行为,就是功能。
面向对象:注重的是对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来 

举个例子: 这里把衣服放进洗衣机、启动洗衣机和将衣服拿出洗衣机都是对洗衣机的操作。这里洗衣机就是一个对象,洗衣机洗衣服的功能就包含在这个对象中。 

2.面向对象设计

面向对象设计把握一个重要的经验:谁拥有数据,谁对外提供操作这些数据(私有)的方法! 

二.类和类的实例化

1.什么是类

类就是一类对象的统称。对象就是这一类具体化的一个实例。

举一个通俗的例子:我们在做饼干的时候会用到模具,模具就是一个类,而模具做出来的饼干就是对象。一个模具能做出多个饼干,那么一个类也能实例化多个对象。接下来用一段代码来展示具体用法:

class Person{
        //成员变量/字段/属性
        public String name;
        public String sex;
        public int age;
        //成员方法/行为
        public void show(String name,String sex,int age){
            System.out.println("姓名:"+name+" 性别:"+sex+" 年龄:"+age);
        }
}

2.类的实例化

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

1. 类只是一个模型一样的东西,限定了类有哪些成员

 2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

3. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东 西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间 

那么怎么实例化一个对象呢?我们通过new来实现

怎么调用类里面的方法呢?我们可以通过 对象引用.成员变量/成员方法 来调用类里面创建的变量及方法。

接下来上一段代码具体演示一下操作: 

class Person{
        //成员变量/字段/属性
        public String name;
        public String sex;
        public int age;
        //成员方法/行为
        public void show(String name,String sex,int age){
            System.out.println("姓名:"+name+" 性别:"+sex+" 年龄:"+age);
        }
}

public class TestDemo {
    public static void main(String[] args) {
        Person person = new Person();//实例化对象
        person.show("Sarah","女",18);//调用show方法
    }
}

就跟我们上面举的例子一样,通过一份设计图能建造多个房子,那么一个类也能实例化多个对象! 

class Person{
        //成员变量/字段/属性
        public String name;
        public String sex;
        public int age;
        //成员方法/行为
        public void show(String name,String sex,int age){
            System.out.println("姓名:"+name+" 性别:"+sex+" 年龄:"+age);
        }
}

public class TestDemo {
    public static void main(String[] args) {
        //实例化多个对象
        Person person1 = new Person();
        Person person2 = new Person();
        person1.show("Sarah","女",18);
    }
}

三.类的成员

类的成员可以包含以下:字段、方法、代码块、内部类和接口等。这里我们重点讲解一下前三个

1.成员变量

定义在类中 、在方法外部的变量,我们称为 "字段" 或 "属性" 或 "成员变量"(三种称呼都可以, 一般不会严 格区分)

我们来看一段代码,试着输出一下成员变量的值

class Person{
        //成员变量/字段/属性
        public String name;
        public String sex;
        public int age;

}

public class TestDemo {
    public static void main(String[] args) {
        //实例化多个对象
        Person person = new Person();
        System.out.println(person.name);
        System.out.println(person.sex);
        System.out.println(person.age);
    }
}

这里我们并没有初始化这三组成员变量,为什么还能输出null、null、0呢?我们在数据类型里面提到过,如果一个对象的成员变量没有显式设置初始值,将会输出默认值,下面是默认值规则,供大家参考:

 注意:不能对null进行访问操作!因为null代表空引用,类似于C语言中的空指针,如果进行访问操作则会发生异常

2.方法

就像我们前面讲的洗衣机是一个对象,那么洗衣机洗衣服的功能就是洗衣机这个对象的方法这里,方法的定义就是 用于描述一个对象的行为

class Person{
    public String name ;
    public int age;

    public void show(String name,int age){
        System.out.println("我叫"+name+",我今年"+age+"岁");
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.show("Sarah",18);
    }
}

  

这里的show方法就是person这个对象自我展示的行为!需要注意的是,这样的 show 方法是和 person 实例相关联的. 如果创建了其他实例, 那么 show 的行为就会发生变化

class Person{
    public String name ;
    public int age;

    public void show(String name,int age){
        System.out.println("我叫"+name+",我今年"+age+"岁");
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.show("Wsy",18);
    }
}

3.static关键字

静态成员变量

我们成员变量分为 普通成员变量和静态成员变量
普通成员变量也叫做实例的成员变量,静态成员变量也叫做类变量 

首先我们来看看怎么访问静态成员变量

class Demo{
        //成员变量/字段/属性
        public static int num1;//创建一个静态成员变量
        public  int num2;//创建一个普通成员变量
}

public class TestDemo {
    public static void main(String[] args) {
        Demo demo = new Demo();
        System.out.println(Demo.num1);
        System.out.println(demo.num1);
    }

}

我们发现通过方法名.静态成员变量虽然能得到结果,但是会有警告,所以我们最好通过类.静态成员变量来访问 静态成员变量

静态成员变量储存方式

我们知道对象是储存到栈上的,那么静态成员变量是储存到哪的呢?

class Demo{
        //成员变量/字段/属性
        public static int num1;//创建一个静态成员变量
        public  int num2;//创建一个普通成员变量
}

public class TestDemo {
    
    public static void main(String[] args) {
        Demo demo = new Demo();
        Demo.num1++;
        demo.num2++;
        System.out.println(Demo.num1);
        System.out.println(demo.num2);
        System.out.println("-------------------");
        Demo demo1 = new Demo();
        Demo.num1++;
        demo1.num2++;
        System.out.println(Demo.num1);
        System.out.println(demo1.num2);
    }

}

来看看运行结果:

为什么在第二次++后num1和num2的值不一样呢?我们发现他们一个是静态成员变量,一个是成员变量,我们来具体分析一下他们储存的位置

通过分析,我们发现由static修饰的静态成员变量压根不依赖于对象!因为它并没有存放在堆上面,而是放在方法区里!无论你new多少个对象,num1就这么一个,所以num1的结果是2!

 来看一个例子来看看静态成员变量的特点

class Demo{
        //成员变量/字段/属性
        public static int num1;//创建一个静态成员变量
        public  int num2;//创建一个普通成员变量
}

public class TestDemo {
    public static void main(String[] args) {
        Demo.num1++;
        System.out.println(Demo.num1);
    }

}

我们知道,如果访问普通成员变量不初始化一个对象是会报错的!但是静态成员变量却能正常运行!归根结底,还是我们前面说的,静态成员变量不依赖于对象!! 

 我们再来看一段代码看看是否会报错

class Demo{
        //成员变量/字段/属性
        public static int num1;//创建一个静态成员变量
        public  int num2;//创建一个普通成员变量
}

public class TestDemo {
    public static void main(String[] args) {
        Demo demo = null;
        System.out.println(demo.num1);
    }

}

我们前面提到了,null.任何东西都会出现空指针引用异常。那么这个时候为什么不报错呢?这里的 demo代表demo不指向任何对象,而我们已经说过静态成员变量的访问时不依赖于对象的,所以这里并没有发生异常。但如果通过 demo访问普通成员变量的话就会报错!

静态成员方法

成员方法也分为两种,一种是普通成员方法,一种是静态成员方法。
普通的成员方法又叫做实例的成员方法,静态的成员方法也叫做类方法。

我们先来看一下静态成员方法如何调用!请看代码 

class Demo{
        //成员变量/字段/属性
        public String name;
        public static void eat(String name){
            System.out.println(name+"在吃饭");
    }
        public void  sleep(String name){
        System.out.println(name+"在睡觉");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        Demo.eat("Sarah");
    }

}

静态成员方法能直接通过 类名.方法进行访问 而普通成员方法需要先实例化一个对象,然后通过 对象名.方法 进行访问

同理可推到出,在静态的成员方法内部也是不可以调用普通成员方法的,除非实例化一个对象 

注意:我们曾经写的方法为了方便直接调用, 都统一加上了 static. 但实际上一个方法具体要不要带 static, 都需要是情形而定.
静态的在类加载的时候就已经定义好了,具体在后面的JVM中会讲解到。

总结-必看!!!

普通方法内部:不能定义静态方法变量static  能调用静态方法

静态方法内部:可以通过实例化对象来调用普通方法

4.toString方法

关于toString方法,我们来看一段代码

class Person{
    public String name ;
    public int age;
    public void show(String name,int age){
        System.out.println("我叫"+name+",我今年"+age+"岁");
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person);
    }
}

 

这里先科普一下序列化和反序列化 

序列化:把一个对象变成字符串
反序列化:把字符串变成对像 

 我们发现这里打印的是一个地址,按住ctrl,点击println,发现调用的是valueOf方法,同样的方法发现最后调用的是Object 的 toString 方法来打印  

我们可以自己写一个toString方法,大家可以自己去实现。这里主要讲IDEA自己生成的toString方法。快捷键是alt+insert

使用toString方法的代码和运行结果如下

class Person{
    public String name ;
    public int age;
    public void show(String name,int age){
        System.out.println("我叫"+name+",我今年"+age+"岁");
    }

    @Override//重写
    public String toString() {
        return "Person{" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '}';
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person);
    }
}

ps:双引号里面的内容可以自己进行修改

5.匿名对象

没有引用的对象称为匿名对象
匿名对象只能在创建对象时使用
如果一个对象只是用一次, 后面不需要用了, 可以考虑使用匿名对象

用法展示: 

public static void main(String[] args) {
        new Person().name = "Sarah";
        new Person().age = 18;
    }

四.封装

面向对象编程的三大特征:继承 封装 多态

在我们写代码的时候经常会涉及两种角色: 类的实现者类的调用者 

封装的本质:让类的调用者不必太多的了解类的实现者是如何实现类的, 只要知道如何使用类就行了. 这样就降低了类使用者的学习和使用成本, 从而降低了复杂程度 

1.private实现封装

private/ public 这两个关键字表示 " 访问权限控制 " .
public 修饰的成员变量或者成员方法 , 可以直接被类的调用者使用
private 修饰的成员变量或者成员方法 , 不能被类的调用者使用

具体private应该在哪种情况下使用呢 ,我们来看一段代码

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+"岁");
    }
}

 

这段运行起来没有任何问题。但是如果我们想把name改成myName,类的使用者就必须大规模得修改自己的代码。其次,类的使用者也必须清楚Person类内部的实现,这样学习成本太高。那么这个时候,我们可以使用封装

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

public class Test {

    public static void main(String[] args) {
        Person person = new Person();
        person.show("Sarah",18);
    }
}

1.此时字段已经使用 private 来修饰,   类的调用者 (main 方法中 ) 不能直接使用, 而需要借助 show 方法。   此时类的使 用者就不必了解 Person 类的实现细节
2.同时如果类的实现者修改了字段的名字,   类的调用者不需要做出任何修改 ( 类的调用者根本访问不到 name, age 这样的字段)
private 不光能修饰字段 也能修饰方法
通常情况下我们会把字段设为 private 属性,   但是方法是否需要设为 public,  就需要视具体情形而定 . 一般我们希望一个类只提供 " 必要的 " public 方法, 而不应该是把所有的方法都无脑设为 public

2.getter和setter方法

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

public class Test {

    public static void main(String[] args) {
        Person person = new Person();
        person.name = "Sarah";
        person.show();
    }
}

这段代码报错,我们来看看报错原因: 

这个时候,如果需要获取/修改private这个属性,就需要使用gette和setter方法

class Person{
    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;//this引用,调用该方法的对象
    }

    public void show(){
        System.out.println("我叫"+name+",我今年"+age+"岁");

    }
}

public class Test {

    public static void main(String[] args) {
        Person person = new Person();
        person.setName("Sarah") ;
        person.setAge(18);
        person.show();
    }
}
getName 即为 getter 方法, 表示获取这个成员的值
setName 即为 setter 方法, 表示设置这个成员的值
set 方法的形参名字和类中的成员属性的名字一样的时候,如果不使用 this, 相当于自赋值。  this 表示当前实例的引用

生成getter和setter方法的快捷键跟生成toString方法一样:alt+insert

五.构造方法

1.基本语法

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

1. 方法名称必须与类名称相同
2.构造方法没有返回值类型声明
3. 每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)
1.如果类中没有提供任何的构造函数,那么编译器会默认生成一个不带有参数的构造函数
2.若类中定义了构造方法,则默认的无参构造将不再生成
3.构造方法支持重载 . 规则和普通方法的重载一致
class Person{
    private String name ;
    private String sex ;
    private int age;
    //默认构造函数 构造对象
    public Person(){
        this.name = "A";
        this.sex = "男";
        this.age = 18;
    }
    //带有三个参数的构造方法
    public Person(String name,String sex,int age){
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
    public void show(){
        System.out.println("name: "+name+" sex: "+sex+" age: "+age);
    }
}

public class Test {

    public static void main(String[] args) {
        Person person1 = new Person();
        person1.show();
        Person person2 = new Person("B","女",18);
        person2.show();
    }
}

2.this关键字

this代表当前对象的引用

this关键字共有三种使用方法

1.this.data:调用当前对象的属性

2.this.func():调用当前对象的方法

3.this():调用当前对象的其他构造方法  (只能存放在构造函数中) 

接下来我们具体看看怎么使用,第一种用法其实我们在上面已经使用过,第二种用法也跟第一种用法大同小异,只不过一个调用的是属性,一个调用的是方法

public Person(String name,String sex,int age){
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

接下来我们具体讲一下第三种使用

 public Person(){
        this("A","女",18);
    }

需要注意的是,this()只能调用一个构造方法,且必须放在构造方法里的第一行使用

六.代码块

1.什么是代码块

 代码块就是使用{}定义的一段代码

代码块分为四种:

本地代码块、静态代码块、实例代码块、同步代码块 

2.本地代码块

public class Main {
    public static void main(String[] args) {
        {
            int a = 10;
            System.out.println(a);
        }
    }
}

用法比较少见,这里不再赘述

3.实例代码块

也叫构造代码块,一般用于初始化实例成员变量

class People{
    private String name;
    private int age;
    {
        this.name = "A";
        this.age = 18;
    }
    public void show(){
        System.out.println("name: "+name+" age: "+age);
    }
}


public class Main {
    public static void main(String[] args) {
        People p = new People();
        p.show();
    }
}

 

4.静态代码块 

使用 static 定义的代码块。 一般用于初始化静态成员属性。
class People{
    private String name;
    private int age;
    private static int count = 0;//静态成员变量 由类共享数据 方法区
    {
        this.name = "A";
        this.age = 18;
        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);
    }
}


public class Main {
    public static void main(String[] args) {
        People p = new People();
        p.show();
    }
}

 

所以我们知道执行顺序为:

静态代码块(只能执行一次、不能调用this方法、不被实例化都能执行)

实例代码块

构造方法

以上是关于Java-类和对象的主要内容,如果未能解决你的问题,请参考以下文章

Java系列类和对象中需要注意的事情

Java——类和对象超详细总结

Java类和对象-学习笔记(超级详细~~~)

10方法的定义和重载和递归

初始Java 来自Java SE的第六节课 类和对象

05-JAVA类和对象