JavaSE:类和对象

类和对象的认识

面向对象和面向过程

**面向过程:**面向过程就是分析出实现某些需求所需要的步骤,然后同股票函数逐步实现,依次调用

**面向对象:**面向对象是把整个需求按照功能、特点划分,将这些存在共性的部分封装成对象,当解决一个问题的时候,面向对象会把事物抽象成对象的概念,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。

类和对象的概念

类就是一类对象的统称,对象就是这一类具体化的一个实例。打个通俗的比喻就是:制作月饼的模具就相当于我们的类,而利用模具做出来的月饼就是我们通过月饼模具“实例化”的一个对象。总的来说:类相当于一个模板,对象是由模板产生的样本,一个类,可以产生无数的对象。声明一个类就是创建一个新的数据类型,而类在 Java 中属于引用类型, 所以Java 使用关键字 class 来声明类。

在这里插入图片描述

类的定义与实例化

//类的定义
class 类名 {
    
    
	成员变量;
    成员方法;
}
//类的实例化-->对象
类名 对象名 = new 类名();

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

class Person {
    
    
    public String name;
    public int age;
    public String sex;
    public void eat() {
    
    
        System.out.println(name+"要吃饭");
    }
    public void sleep() {
    
    
        System.out.println(name+"要睡觉");
    }
}

稍后我们会解释一直未解释的public以及我们这里写方法时为什么没加static

用类创建对象的过程,称为类的实例,一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量,new关键字用于创建一个对象,使用 . 来访问对象中的属性和方法

在这里插入图片描述

class Person {
    
    
    public String name = "lrf";
    public int age = 19;
    public String sex = "man";
    public void eat() {
    
    
        System.out.println(name+"要吃饭");
    }
    public void sleep() {
    
    
        System.out.println(name+"要睡觉");
    }
}

class Main {
    
    
    public static void main(String[] args) {
    
    
          Person person = new Person();//类的实例化-->创建对象

          person.eat();
          person.sleep();
    }
}

在这里插入图片描述

类和对象的内存结构

在这里插入图片描述

person是一个变量,只是这个变量里储存的是地址,所以这个变量也被叫做引用

类的成员

字段/属性/成员变量

在类内,在方法外部定义的变量我们称为 “字段” 或 “属性” 或 "成员变量,用于描述一个类中包含哪些数据

class Person {
    
    
    public String name = "lrf";//字段/属性/成员变量
    public int age = 19;//字段/属性/成员变量
    public String sex ;//字段/属性/成员变量
    public void eat() {
    
    
        System.out.println(name+"要吃饭");
    }
    public void sleep() {
    
    
        System.out.println(name+"要睡觉");
    }
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        Person person = new Person();//类的实例化-->创建对象
        //字段的访问
        System.out.println(person.name+"的年龄是:"+person.age);
        //字段的默认值
        System.out.println(person.name+"的性别是:"+person.sex);
    }
}

在这里插入图片描述

总结:

1.使用.来访问对象的字段,访问包含读和写

2.一个对象的字段如果没有显式设置初始值,那么会被设置一个默认的初值

默认值规则

  • 8种基本数据类型, 默认值为 0.
  • boolean类型,默认值为false
  • 引用类型(String, Array, 以及自定制类), 默认值为null

方法

我们之前以及讲过了方法,他可以理解为函数的别名,我们定义的方法用来描述对象的行为

class Person {
    
    
    public String name;
    public int age;
    public void describe() {
    
    
        System.out.println("我叫"+name+",是一名"+age+"岁的成年男性,"+"也被人称为“法外狂徒”"+name);
    }
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        Person person1 = new Person();//类的实例化-->创建对象
        person1.age = 23;
        person1.name = "张三";
        person1.describe();
        Person person2 = new Person();
        person2.age = 13;
        person2.name = "李四";
        person2.describe();
    }
}

在这里插入图片描述

此处的describe方法, 表示我们实例化对象之后,这个对象具有一个"自我介绍"的行为,我们类中定义的方法是和实例化的对象相关联的,如果创建了其他实例, 那么describe的行为就会发生变化

static关键字

class staticTest {
    
    
    public static int count=0;
    public int age=0;
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        staticTest person1 = new staticTest();
        person1.count++;
        person1.age++;
        System.out.println("person1.count="+person1.count);
        System.out.println("person1.age="+person1.age);
        staticTest person2 = new staticTest();
        person2.count++;
        person2.age++;
        System.out.println("person2.count="+person1.count);
        System.out.println("person2.age="+person1.age);
    }
}

在我们为了解static的作用之前,我们认为应该输出person1.count=1person1.age=1person2.count=1person2.age=1,毕竟在定义类时,两者都初始化为0,那么我们运行以下上述代码,结果真如我们所想吗?

在这里插入图片描述

age变量如我们所想象的一样,那么count变量为什么会是1和2呢?

由static修饰的变量和方法被称作静态变量、静态方法,又称为类变量。类方法。静态成员是属于类所有的,区别于个别对象,可以在本类或其他类中使用类名和.运算符调用。这里先接受以下Java内存中的方法区,然后我们从内存角度去剖析以下具体的原因

在这里插入图片描述

**方法区:**保存在着被加载过的每一个类的信息,这些信息由类加载器在加载类的时候,从类的源文件中抽取出来,static变量和方法的信息也保存在方法区中

在这里插入图片描述

以下是内存角度分析:
在这里插入图片描述

注意&总结:

1.普通的方法内部,不能够定义静态的变量

2.静态方法的内部不可以调用普通方法

3.我们曾经说写方法都要统一加上了static,是因为我们之前写的方法只有被static修饰后才能直接调用而不依赖于对象

4.一个对象存储到哪里,和是否被final修饰没有任何关系

封装

访问限定修饰符

private/ public 这两个关键字称为访问限定修饰符

  • public修饰的成员变量或者成员方法,可以直接被类的调用者使用
  • private修饰的成员变量或者成员方法,不能被类的调用者使用
class Test {
    
    
    public int count=1;
    public int age=13;
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        Test test = new Test();
        System.out.println(test.age);
        System.out.println(test.count);
    }
}

当我们将变量使用public修饰时,在类外访时需要了解Test类内部的实现,才能够使用这个类,学习成本较高,一旦类的实现者修改了代码(把count改成num),那么类的使用者就需要大规模的修改代码,这使得代码的可维护性较低,维护难度较大,维护成本较高。为了解决这些问题,提高我们代码的可维护性,我们提出了封装这个概念。

封装可以被认为是一个保护罩,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制,我们的getter和setter方法来源就是如此。

getter和setter方法

我们使用private封装属性, 并提供public的getter和setter方法供类的调用者去访问这些属性。

class Test {
    
    
    private String name = "张三";
    private int age = 23;

    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;
    }
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        Test test = new Test();
        System.out.println(test.getName()+"的年龄是:"+test.getAge());
        test.setName("李四");
        test.setAge(33);
        System.out.println(test.getName()+"的年龄是:"+test.getAge());
    }
}

this表示当前对象引用(注意不是当前对象). 可以借助 this 来访问对象的字段和方法,稍后我们详细介绍

注意&总结:
1.getName即为getter方法,表示获取这个成员的值,setName即为setter方法,表示修改这个成员的值.

2.当set方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this,就相当于自己给自己赋值,this表示当前对象的引用
3.不是所有的字段都一定要提供 setter / getter 方法,要根据实际情况决定提供哪种方法

IDEA生成getter / setter方法快捷方法:

在这里插入图片描述

构造方法

一个对象的产生要有两个过程:

1.为对象分配内存

2.调用合适构造方法

什么是构造方法?

构造方法是一种特殊方法, 使用关键字new实例化新对象时会被自动调用, 用于完成初始化操作,就算我们在类中没有实现构造方法,那么编译器也会自动帮我们生成一个无参的构造方法,也就是说:一个类至少有一个构造方法

基本语法

1.方法名与类名相同

2.构造方法没有返回值类型的声明

示例:

class Test {
    
    
    public String name ;
    public int age;
    public Test(int age) {
    
    
        this.age = age;
    }
    public Test(String name) {
    
    
        this.name = name;
    }
    public Test(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        Test test1 = new Test(1);//参数为age的构造方法
        System.out.println("test1: ");
        System.out.print(test1.age+" ");
        System.out.println(test1.name);
        Test test2 = new Test("wuhu~");//参数为name的构造方法
        System.out.println("test2: ");
        System.out.print(test2.age+" ");
        System.out.println(test2.name);
        Test test3 = new Test("wuhu~",1);//两个参数的构造方法
        System.out.println("test3 ");
        System.out.print(test3.age+" ");
        System.out.println(test3.name);
    }

在这里插入图片描述

this关键字

this表示当前对象引用,注意不是当前对象. 在一些特殊情况下必须借助 this来访问对象的字段和方法

class Test {
    
    
    public String name ;
    public int age;
    public Test(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        Test test3 = new Test("wuhu~",1);//两个参数的构造方法
        System.out.println("test3 ");
        System.out.print(test3.age+" ");
        System.out.println(test3.name);
    }
}

例如我们在写构造方法时,我们传入的参数名和成员变量名如果是相同的,那么就会造成歧义导致程序结果与预期不符,当我们使用this关键字时,便可以对两个相同名字的变量进行区分。

class Test {
    
    
    public String name ;
    public int age;
    public Test(String name, int age) {
    
    
        name = name;
        age = age;
    }
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        Test test3 = new Test("wuhu~",1);//两个参数的构造方法
        System.out.println("test3 ");
        System.out.print(test3.age+" ");
        System.out.println(test3.name);
    }
}

在这里插入图片描述

代码块

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

普通代码块

一般很少这样使用

class Test {
    
    
    public String name ;
    public int age;
    public Test(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
}
class Main {
    
    
    public static void main(String[] args) {
    
    
        //定义一个普通代码块
        {
    
    
            System.out.println("我是普通代码块");
            String str = "hhh";
            System.out.println(str);
        }
    }
}

在这里插入图片描述

构造代码块与静态代码块

实例代码块也称为构造代码块

  1. 构造代码块的作用是给对象进行初始化。
  2. 对象一建立就运行构造代码块了,而且优先于构造函数执行。这里要强调一下,有对象建立,才会运行构造代码块,类是不能调用构造代码块的,而且构造代码块与构造函数的执行顺序是前者先于后者执行
  3. 构造代码块与构造函数的区别是:构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化,因为构造函数是可以多个的,运行哪个构造函数就会建立什么样的对象,但无论建立哪个对象,都会先执行相同的构造代码块。也就是说,构造代码块中定义的是不同对象共性的初始化内容。

静态代码块

  1. 它是随着类的加载而执行,只执行一次,并优先于主函数。具体说,静态代码块是由类调用的。类调用时,先执行静态代码块,然后才执行主函数的。
  2. 静态代码块其实就是给类初始化的,而构造代码块是给对象初始化的
  3. 静态代码块中的变量是局部变量,与普通函数中的局部变量性质没有区别。
  4. 一个类中可以有多个静态代码块

可根据以下代码以及运行结果去对照分析上述规则:

    class Test {
    
    
        public static int num = 233;
        public String name ;
        public int age;

        public Test(String name, int age) {
    
    
            this.name = name;
            this.age = age;
        }
        {
    
    
            System.out.println("现在执行到了实例代码块");
            num = 23;
            name = "hhh";
            System.out.println("在执行到实例代码快时:");
            System.out.println("name = "+name+"  age = "+age);
        }
        static{
    
    
            num = 123;
            System.out.println("现在执行到了静态代码块");
        }
    }
    class Main {
    
    
        public static void main(String[] args) {
    
    
            System.out.println(Test.num);//调用类(未实例化对象)
            Test test = new Test("hehe",1);
            System.out.println("对象实例化之后:");
            System.out.println("test.naem = "+test.name+" test.age = "+test.age);
        }
    }

在这里插入图片描述

toString

toString 方法会返回一个“以文本方式表示”此对象的字符串。你想将一个对象以字符串的方式输出时。如果默认继承Object类的话,就是将对象以“类名@ 对象hashcode字符串输出,toString方法会在println的时候被自动调用.

    class Test {
    
    
        public String name = "hhh";
        public int age = 123;
    }
    class Main {
    
    
        public static void main(String[] args) {
    
    
            Test test = new Test();
            System.out.println();
        }
    }

在这里插入图片描述

toString是Object类提供的方法, 我们自己创建的Test类默认继承自Object类,可以重写 toString 方法实
现我们自己版本的转换字符串方法。

class Test {
    
    
        public String name = "hhh";
        public int age = 123;

    @Override
    public String toString() {
    
    
        return "Test{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
class Main {
    
    
        public static void main(String[] args) {
    
    
            Test test = new Test();
            System.out.println(test);
        }
}

在这里插入图片描述

@Override在Java中称为 “注解”,此处的@Override表示下面实现的toString方法是重写了父类的方法

匿名对象

匿名对象:就是没有名字的对象,如果一个对象只是用一次, 后面不需要用了, 可以考虑使用匿名对象

1.没有引用类型的变量指向的对象称为匿名对象

2.匿名对象只能在创建对象时使用.

3.两个匿名对象永远不可能是同一个对象

class Test {
    
    
        public String name = "hhh";
        public int age = 123;
}
class Main {
    
    
        public static void main(String[] args) {
    
    
            System.out.println(new Test().toString());//两个匿名对象永远不可能是同一个对象
            System.out.println(new Test().toString());//两个匿名对象永远不可能是同一个对象
            System.out.println(new Test().age);//匿名对象只能在创建对象时使用
            System.out.println(new Test().name);//匿名对象只能在创建对象时使用
        }
}

在这里插入图片描述

鉴于笔者水平有限,本文可能存在些许错误,请大家批评指正!

猜你喜欢

转载自blog.csdn.net/qq_37410388/article/details/121366237