• 认识Java中的类和对象(上)


    作者:~小明学编程 

    文章专栏:JavaSE基础

    格言:目之所及皆为回忆,心之所想皆为过往。
    在这里插入图片描述

    目录

    面向对象

    什么是面向对象

    面向对象与面向过程

    类的定义和使用

    简单认识类

    类的定义格式

    类中的static

    static修饰过的变量

    静态成员变量定义的位置

    static修饰过的方法之间的调用

    封装

    什么是封装

    private实现封装

    自动生成Setter和Getter


    面向对象

    什么是面向对象

    Java是一门纯面向对象的语言(Object Oriented Program,继承OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。

    面向对象与面向过程

    面向对象是只关注我们的结果,而面向过程顾名思义就是注重过程,讲究的是一步一步实现,而面向对象则是封装好的东西我们直接拿来用就可以了。

    类的定义和使用

    简单认识类

    类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。
     

    比如:洗衣机,它是一个品牌,在Java中可以将其看成是一个类别。
    属性:产品品牌,型号,产品重量,外观尺寸,颜色...
    功能:洗衣,烘干、定时
     


    类的定义格式

    在java中定义类时需要用到class关键字,具体语法如下

    1. // 创建类
    2. class ClassName{
    3. field; // 字段(属性) 或者 成员变量
    4. method; // 行为 或者 成员方法
    5. }

    class为定义类的关键字,ClassName为类的名字,{}中为类的主体
    类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。

    1. class Person {
    2. public String name;
    3. public int age;
    4. public void eat() {
    5. System.out.println(name+"在吃饭……");
    6. }
    7. public void print() {
    8. System.out.println("姓名:"+name+" 年龄:"+age);
    9. }
    10. }
    11. public class Dome {
    12. public static void main(String[] args) {
    13. Person person = new Person();
    14. person.name = "张三";
    15. person.age = 20;
    16. person.eat();
    17. person.print();
    18. }
    19. }

    采用Java语言将洗衣机类在计算机中定义完成,经过javac编译之后形成.class文件,在JVM的基础上计算机就可以识别了。
    注意事项
    1.类名注意采用大驼峰定义。
    2.成员前写法统一为public,后面会详细解释。
    3.此处写的方法不带 static 关键字. 后面会详细解释。

    内存布局 

    这里简单给大家介绍一下内存布局我们在主方法中new了一个对象,person是一个变量存放在栈区,它的值是一个地址,我们也把这个变量叫做引用(不是所有的引用都放在栈区,我们类中的成员也可以是一个引用,此时的引用就放在了堆区),person的类型是Person是一个类,我们new出来的是一个新的对象,我们可以通过引用找到这个对象并对其进行各种操作。

    类中的static

    static修饰过的变量

    我们看一下下面这段代码

    1. class Person {
    2. public String name;
    3. public int age;
    4. public int count;
    5. public static int count1;
    6. public void eat() {
    7. System.out.println(name+"在吃饭……");
    8. }
    9. public void print() {
    10. System.out.println("姓名:"+name+" 年龄:"+age);
    11. }
    12. }
    13. public class Dome {
    14. public static void main(String[] args) {
    15. Person person1 = new Person();
    16. Person person2 = new Person();
    17. person1.count++;
    18. person1.count1++;
    19. System.out.println("count="+person1.count);
    20. System.out.println("count1="+person1.count1);
    21. person2.count++;
    22. person2.count1++;
    23. System.out.println("count="+person2.count);
    24. System.out.println("count1="+person2.count1);
    25. }
    26. }

    我们在类中定义了一个count和一个count1一个用static修饰了一个没用,然后在主函数中我们定义了两个变量person1和person2,通过前面的学习我们知道我们通过这两个引用,引用它们的对象是互不干扰的,所以我们的count应该都是1。

     但是这里我们看到count是1没有错但是count却是有增长,这又是什么原因呢?

    想要了解这个问题的话我们首先得知道类在内存中的布局。

     通过前面的学习我们知道方法区会存放我们类的代码部分代码片段,还会存放我们的静态成员变量,所以我们的count1不是存放在堆里面的而是放在我们的方法区中的,这就相当于我们在C语言中函数中定义一个静态变量这个count1的值不唯一与person1或者person2有关,而是直接关系着Person,所以我们一般就直接写成这种格式,也就是直接通过类找到这个变量,也就是说我们静态成员变量是不依赖对象来访问的,我们也可通过类名.静态成员变量来访问。

            Person.count1++;
    

    同理我们的在方法前面加static也是这么一个道理。

    1. class Person {
    2. public String name;
    3. public int age;
    4. public int count;
    5. public static int count1;
    6. public void eat() {
    7. System.out.println(name+"在吃饭……");
    8. }
    9. public void print() {
    10. System.out.println("姓名:"+name+" 年龄:"+age);
    11. }
    12. public static void fun() {
    13. System.out.println("hello world!");
    14. }
    15. }
    16. public class Dome {
    17. public static void main(String[] args) {
    18. Person.fun();
    19. }
    20. }

    直接通过类就可以调用我们的fun方法了。

    静态成员变量定义的位置

    我们要知道我们的静态成员变量也就是被static修饰的变量是不能定义在方法中的,只能定义在我们的类之中,不然就会报错。

     注意

    1.static定义的变量,类变量,属于类。

    2.eat方法的调用需要对应的引用来调用,但是如果可以定义static的变量,Person就可以调用。

    3.静态变量不能在方法中定义。

    static修饰过的方法之间的调用

    在Java中我们普通的方法是可以调用static修饰过的静态的方法,但是static修饰的静态方法是不能够调用我们普通的没有被static修饰过的方法的。

    1. public static void fun() {
    2. fun1();
    3. System.out.println("hello world!");
    4. }
    5. public void fun1() {
    6. fun();
    7. System.out.println("hello");
    8. }

     这里也很好理解,因为我们普通方法是依赖对象的而静态方法是依赖类的,有类我们就能用,所以我们用普通方法的时候肯定有对象,既然有对象也肯定有类,但我们用静态方法的时候只能证明它有类,但不一定有对象,所以我们的静态方法不能直接调用我们的普通方法,同理我们可以知道静态方法也可以调用静态方法。


    封装

    什么是封装

    封装将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

    private实现封装

    在认识封装之前我们先看一下下面这段代码

    1. class Person {
    2. public int age;
    3. public String name;
    4. public void fun() {
    5. System.out.println("hello");
    6. }
    7. @Override
    8. public String toString() {
    9. return "Person{" +
    10. "age=" + age +
    11. ", name='" + name + '\'' +
    12. '}';
    13. }
    14. }
    15. public class Dome {
    16. public static void main(String[] args) {
    17. Person person = new Person();
    18. person.name = "张三";
    19. person.age = 18;
    20. System.out.println(person);
    21. }
    22. }

    我们在我们的Person类里面定义了一个成员变量name如果我们想要把这个成员变量name改为myname时这时候不仅是我们类里面需要改,我们所有的引用Person类中的name全部都要改为myname如果我们这个类的使用者很多的话,无疑将是一个繁琐的工程,那么如何解决上述问题呢?

    1. public void setName(String myName) {
    2. name = myName;
    3. }
    4. public String getMyName() {
    5. return name;
    6. }

    我们可以通过上述的方式,提供两个公开的接口来完成我们对name的赋值和使用,此时我们的name已经被封装起来了不能通过对象来直接调用我们的那么,这时候我们想要把name改为name1就可以直接把类里面的name改为name1就行了。

    1. class Person {
    2. public int age;
    3. private String name1;
    4. public void fun() {
    5. System.out.println("hello"+name1);
    6. }
    7. public void setMyName(String myName) {
    8. name1 = myName;
    9. }
    10. public String getMyName() {
    11. return name1;
    12. }
    13. @Override
    14. public String toString() {
    15. return "Person{" +
    16. "age=" + age +
    17. ", name='" + name1 + '\'' +
    18. '}';
    19. }
    20. }
    21. public class Dome {
    22. public static void main(String[] args) {
    23. Person person = new Person();
    24. // person.name = "张三";
    25. person.setMyName("张三");
    26. person.age = 18;
    27. System.out.println(person);
    28. person.fun();
    29. }
    30. }

     这时我们把name改为name1只需要把类里面的name修改就行了,同时也增强了,我们成员变量name的安全性。

    那么当我们的封装的变量过多时怎么办呢?一个一个写接口的话太浪费时间了,这时我们可以通过编译器自动生成接口函数。

    自动生成Setter和Getter

    第一步:在类中的空白处单击右键找到Generate

     第二步:找到Getter和Setter可以按需要只生成Getter或者Setter也行

     第三步:选择我们要封装的成员变量

    1. public int getAge() {
    2. return age;
    3. }
    4. public void setAge(int age) {
    5. this.age = age;
    6. }

    this.age指的是调用该类的成员变量这样就防止了把age误认为局部变量。


  • 相关阅读:
    javascript二维数组(19)不要键名只保留值的算法
    数据结构-并查集刷题
    Educational Codeforces Round 136 (Rated for Div. 2) 补题题解 (A、B)
    Mac删除不在程序坞的程序
    驱动day4
    uni-app华为审核被拒,驳回原因:您的应用在运行时,未见向用户告知权限申请的目的
    pandas 识别并取出重复项
    【Educoder作业】C&C++控制结构实训
    Makefile 常见的错误信息
    2022:图元文件转换为Xaml||Paste2Xaml & ReaderWmf
  • 原文地址:https://blog.csdn.net/m0_56911284/article/details/126461867