整理版:java类与对象知识框架总结(超级详细)

一:框架搭建

首先我们先把java代码的每一块部分的顺序,位置进行框架,比如类在哪里,main方法在哪里,成员变量又在哪里,构造方法又该写在哪等等,然后我们再一块一块的进行分析

一:最大的两个框架

首先,这是最大的两个框架(当然,它们都属于同一个包里面)

一般class 类名是我们自己编写的类,而public class 主类名则是每个java文件必备的一个类

c19548f1816841abab77d69ffea4fee6.png

二:class类和主类里面的框架

我们先解构class类

class类中往下分,整体分为三个部分:成员变量区,构造方法区,成员方法区

9e52d7d535fe4a8c8eb6fcb4a5539da7.png

再解构主类

主类往下分,整体分为四个部分:成员变量区,构造方法区,main方法区,成员方法区(一般编写顺序如下,但也可以进行顺序上的调整)

40233cdad7f24ba2bea5a83a308ebfac.png

三:分析每个小块的框架

1.class类里的成员变量区

92cc0fcfbca441d59d26d9cfc8d6acd8.png

当我们创建成员变量时,要么定义的时候就赋值,要么就不赋值,等着后面的构造方法或者成员方法来进行赋值。

接下来我们就要重点解释访问限定符:

访问限定符:

private ,  default(也就是变量前面什么都没写,系统默认给的访问限定符) ,  public

(protected因为牵扯到继承的父类和子类,在本篇只讲类和对象的原因下,就不讲了)

一:private:

该变量能使用的范围:同一个包的同一个类

用我们刚刚搭建的框架来表示,就在这一块范围内,private修饰的变量都能使用

7994cbbd335e4214ba9727649266c52c.png

也就是说,如果出了这个红色圈范围,那么这个private修饰的变量就不能用了

二:default

该变量能使用的范围:同一个包的不同类

用我们刚刚搭建的框架来表示,就在这一块范围内,default的变量都能使用

c4f528a68d3a4bbf81066bd4f5164da1.png

也就是说,如果出了这个红色圈的范围(即如果是其他包要使用default的变量),default变量就不能使用

三:public

该变量能使用的范围:不同包的不同类(人话:哪都能用)

用我们刚刚搭建的框架来表示,就在这一块范围内,public的变量都能使用

f8e43db500374159b245936b54ea9d76.png

2.class类里的构造方法区

8319f3c0ff534bdf9cedac2eb75ba808.png

这里面就可以写各种各样的构造方法,有关构造方法的知识点总结如下

构造方法知识总结:

1.我们可以不写任何的构造方法,这时系统会默认帮我们写一个无参的构造方法,但是我们一旦自己写了任何一个构造方法,那么系统就不会帮我们写那个无参的构造方法

举个例子:我们不写时,有一个无参构造方法。然后我们写了一个带参的构造方法,这时我们拥有的构造方法只有这个带参的构造方法,无参的那个构造方法就消失了,所以如果我们需要无参的构造方法,我们必须自己给它补上

2.当我们写构造方法的时候,如果要写2个及以上的构造方法,那么这个时候就叫做构造方法的重载,这时我们要从传参的个数,传参的类型,以及传参的顺序来进行区分,如果出现所有都一模一样的话,就会报错

3.创建对象的时候,就会调用构造方法,即通过new来调用,例如 Animal dog=new Animal();

4.如果要在构造方法中调用其他构造方法,要用this(),并且this()这行代码必须放在构造方法的第一行

5.不能形成环,即A构造方法里面调用B构造方法,B构造方法里面又调用A构造方法

例如

class Animal{
    //成员变量区
    String name;
    int age;
    //构造方法区
    public Animal(String name){  //带有一个参数的构造方法
        this.name=name;
        age=3;
    }
    public Animal(String newName,int age){  //带有两个参数的构造方法
        this(newName);  //用this进行构造方法里面调用其他的构造方法
        this.age=age;
    }
}

5.根据上面这段代码,我们也知道,如果当传入的形参和成员变量同名时,可以通过this.来表示这个是成员变量

3.class类里的成员方法区

9d4a279a47e34a6297d118b1cd9bff9f.png

这时候我们要注意了:我们之前定义的变量都叫成员变量,换个通俗一点的名字就是全局变量

而现在我们在方法里面定义的变量就叫局部变量了

局部变量与全局变量的不同点:

1.全局变量(成员变量)可以初始化也可以不初始化,就像我们刚刚上面写的一样,可以定义的时候就赋值,也可以定义的时候不赋值。但是局部变量必须进行初始化,即必须在定义的时候赋值,不然就会报错

2.生命周期不一样,局部变量只要当程序运行走出了方法,那么这个局部变量就会被销毁,相当于这个变量就不存在了,而成员变量只要通过类创建了对象,只要这个类的对象还在,那么这个成员变量还可以继续使用,也就是仍然存在

顺便提一嘴,如果用了static(静态)来修饰类,方法或者变量的话,那么简单理解就相当于永生了,即只要你还没关闭这个idea或者其他的编译器,它都可以使用

大致内存分布如下,本文就不细讲了

1635c7922658400ca9fb5564c3c9e6d4.png

4.主类里的main方法区

主类的成员变量区和构造方法区与class类里面基本一样(因为都是类),就不再解构一遍了

24c815910f954c71ac67f1df8a14713c.png

封装:

就相当于main方法区是一个厨房,你要完成一道菜品(实现题目要求),要调用所需食材(调用各种类),调用所需调料(调用各种方法),而一般来说,食材都是拿塑料袋装着的,调料都是拿瓶子罐子装着的,这样子调用就会很方便,这种思想也就是封装

5.主类里的成员方法区

e407e80f8e4f4670b8c58e69dfdeb76c.png

跟class类里的成员方法区基本一样

二:什么是类和对象

简单来说就是克隆

就像电影里面,克隆得先要有母体,而这个母体就相当于java里的类,这个母体必须要具备什么样的特性,就是由我们来决定的

比如我想克隆一堆学生,那么我们再设计母体(类)的时候,就要添加其特性:比如这个学生得要有名字,得要有年龄,得要有性别等等,把我们想要的特性加进去,不想要的特性就可以不加,

这时候母体设计好了,就可以开始克隆了,克隆出了的克隆体就相当于java里的对象,但是我们也想把每个克隆体作一些区分,比如像电影里代号克隆人一号,克隆人二号等等,就是在母体的基础上进行微调

结合我们上面搭建的框架,简单进行对应:

class类里的成员变量区——设计母体时加我们想要的特性(名词)

class类里的构造方法区——在母体的基础上进行微调(修改名词)

class类里的成员方法区——母体的具体能实现的动作和能力(动词)

举个例子:

这段代码就相当于我设计了一个狗的母体(这时dog就称作为类)

class dog {
    //成员变量区
    String name;
    int age;
    //构造方法区
    public dog(String newName,int newAge){
        this.name=newName;
        this.age=age;
    }
    //成员方法区
    public void eat(){
        System.out.println("吃吃吃");
    }
    public void bark(){
        System.out.println("汪汪汪");
    }
}

这段代码就相当于我克隆了两条狗,并通过构造方法在母体的基础上进行了微调(此时g1,g2就称作为对象)

public class J54 {
    public static void main(String[] args) {
        dog g1=new dog("旺财",3);
        dog g2=new dog("大黄",4);
    }
}

 这段代码就相当于我命令克隆的两条狗进行动作行为(通过对象.成员方法)

public class J54 {
    public static void main(String[] args) {
        dog g1=new dog("旺财",3);
        dog g2=new dog("大黄",4);
        g1.eat();
        g1.bark();
        g2.eat();
        g2.bark();
    }
}

三.代码块

在上面我们搭建的框架基础上,还会加入一些部分——代码块

代码块可分为这四部分:普通代码块,构造块,静态块,同步代码块(多线程部分再谈,这里就不介绍了)

1.普通代码块

作用:我们刚刚讲了局部变量和成员变量的生命周期,如果我们不想让它们的生命周期为默认的范围的话,我们就可以用普通代码块进行修改

public class J54 {
    public static void main(String[] args) {
        //普通代码块
        {
            int x=10;
            System.out.println("x1="+x);
        }

        int x=100;
        System.out.println("x2="+x);
    }
}

也就是我们用{}里面的内容就叫做普通代码块,其中普通代码块里的x的生命周期就在出了{}后就销毁


2.构造代码块(也叫实例代码块)

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

class Student{  //类
    //成员变量区
    private String name;
    private String gender;
    private int age;
    private double score;
    //构造方法区
    public Student(){
        System.out.println("我是无参构造方法");
    }
    //实例代码块
    {
        this.name="bit";
        this.age=12;
        this.score=100;
        System.out.println("我是实例代码块");
    }
    //成员方法区
    public void show(){
        System.out.println("我是成员方法");
    }
}
public class J54 {  //主类
    public static void main(String[] args) {   //main方法区
        Student stu=new Student();  //创建对象
        stu.show();  //调用对象的方法
    }
    //主类里的成员方法区
    public static void func(){
        System.out.println("我是主类里的成员方法");
    }
}

这段代码就是实例代码块的用途,同时也是我们上面搭建整体框架的一个完整样例

注意:实例代码块只有在创建对象时才会执行,类比我们说的克隆,就相当于如果我们在设计母体时对母体进行了修改(编写实例代码块),但我们不进行克隆(不创建对象),那么它永远只在母体上(只存在类里面),也就不会执行我们修改的任何地方(不会执行实例代码块)

3.静态代码块

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

在将静态代码块之前,我们再简单讲一下静态,也就是static

什么是静态(static)

刚刚我们简单提到了被static修饰的,就相当于永生,同时内存分配也会专门分配到static静态区,这是我们表面知道的,但是其深层意义是——被static修饰的就不依赖于对象了,而是属于类,也就是大家可以共享了

我们还是用克隆来类比,刚刚实例代码块是必须在克隆的过程中才会被执行(创建对象时才执行),如果不克隆就不执行(不创建对象就不执行),而静态代码块相当于是母体直接活了,也就是说母体不再只是一个死的样本了,而能够像具有生命的生物体一样进行一切操作,同时与其他克隆体建立了链接,跟Java语言里面进行对应,大致如下:

通过对象修改静态成员变量的话,类中的值也会被修改——对克隆体进行特性上的改造,因为建立了链接,母体的特性也会跟着被改造

通过类 . 静态成员方法也可以直接使用——母体活了,母体自己执行其动作或能力

静态方法总结

1.不属于某个具体的对象,是类方法

2.可以通过对象调用(因为母体和克隆体建立了链接),也可以通过类名.静态方法名调用,但更推荐后者

3.不能在静态方法中访问任何非静态成员变量(因为没被静态的是不共享的,就相当于你说你要请客,但是又要掏别人钱包去买一部分单,不合理)

静态代码块

使用方法

static{

…………

}

花括号{}里面的就是静态代码块

举例:

class Student{  //类
    //成员变量区
    private String name;
    private String gender;
    private int age;
    private double score;
    private static int ID;
    //构造方法区
    public Student(){
        System.out.println("我是无参构造方法");
    }
    //实例代码块
    {
        this.name="bit";
        this.age=12;
        this.score=100;
        System.out.println("我是实例代码块");
    }
    //静态代码块
    static{
        ID=666;
        System.out.println("我是静态代码块");
    }
    //成员方法区
    public void show(){
        System.out.println("我是成员方法");
    }
}
public class J54 {  //主类
    public static void main(String[] args) {   //main方法区
        Student stu=new Student();  //创建对象
        stu.show();  //调用对象的方法
    }
    //主类里的成员方法区
    public static void func(){
        System.out.println("我是主类里的成员方法");
    }
}

可以看到,我们用静态代码块对ID这个静态成员变量进行了初始化

静态代码块总结

1.静态代码块不管生成多少个对象,其只会执行一次(因为只有母体这么一个,无论克隆多少个克隆体,母体也只有一个)

2.如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(相当于既对母体的头部进行了改造,腿部也进行了改造,按照先上后下,那么改造的顺序就是先头部再腿部)

四.打印对象

问题

我们看到一个对象,我们想知道它的所有信息,就想要把它的信息全部打印下来给我们看,但是如果直接打印对象,我们只能打印出它的地址

public class Person{  //主类
    //主类的成员变量区
    String name;
    String gender;
    int age;
    //主类的构造方法区
    public Person(String name,String gender,int age){
        this.name=name;
        this.gender=gender;
        this.age=age;
    }
    public static void main(String[] args) {   //main方法区
        Person person=new Person("jim","男",18);  //创建对象
        System.out.println(person);  //打印对象
    }
}

例如我们想打印jim,男,18这个对象,但是只会打印出这个对象的地址(也就是我们上面画的栈,堆,静态区内存图里面的栈中的引用变量的地址)

打印如下:

9b0f21781d6b4309b06ebaa03a3b69c2.png

如果不理解的话,还是拿克隆来举例子,我们遇见了一个克隆体,我们想知道这一个克隆体的一切特性和能力,就像把它的资料打印出了,结果我们直接打印的话,只打印出了它的生产地址

那么我们该怎么办呢?

解决办法

重写toString方法

public class Person{  //主类
    //主类的成员变量区
    String name;
    String gender;
    int age;
    //主类的构造方法区
    public Person(String name,String gender,int age){
        this.name=name;
        this.gender=gender;
        this.age=age;
    }
    //主类的成员方法区
    public String toString(){
        return "["+name+","+gender+","+age+"]";
    }
    public static void main(String[] args) {   //main方法区
        Person person=new Person("jim","男",18);  //创建对象
        System.out.println(person);  //打印对象
    }
}

打印如下:

fda6e1b4246c4ae89ac7342236f0ef7d.png

背后原因

简单来说,就是IDEA在编写System.out.println()这个方法时,又调用了其他方法来编写System.out.println(),其中有一个被调用的方法就是public String toString(),这个方法就是用来处理System.out.println()里如果接收到是对象名时,会打印这个对象的地址

于是我们直接重写了public String toString(),这样子System.out.println()遇见对象名时,则会调用我们自己写的public String toString(),系统的public String toString()就不被调用了

 

有关类和对象的知识基本讲的七七八八了,希望能通过这篇文章能将所有类和对象的知识点都串起来,把零散的知识点都组合起来

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值