类 和 对象

类 和 对象


每博一文案

让你受伤的往往不是别人,而是你自己的心。

别人言语讽刺你,以便自己生闷气,别人出口污蔑你,你就感到非常委屈。

出门不小心被石头绊了一跤,或者错过了公交,导致迟到都会让你自愿质疑,不停抱怨,满身的缠绕着赋能量。

但是你有没有想过,你之所以身体受伤,是因为你把别人污蔑你的话听进了你的心里,明知道这些话不是真的,你为什么还把他放在心里,不小心被石头绊倒或者迟到,

也只是短时间的惊慌不快,何必要将这种薄块继续发酵,导致接下来的一天都很难受呢。
—————— 一禅心灵庙语


类 和 对象

  • 类就相当是一个模板,与C语言中的结构体类似,不过 Java 中的类更加的多样,更加的复杂,存在着更多的属性,而对象就是通过这个类的模板产生出来的样本,所以一个类可以产生多个对象,但是每个对象,都是相互独立的,互不干扰的,关于这一点后面会详细介绍的,
  • 声明一个类就是创建一个新的数据类型,是和C语言中的结构体设定差不多的,而类在Java当中是属于引用类型的
  • 注意一个类就会生成一个类文件(class),所以一般都是一个文件中一个类的
  • 不可以把一个同名的类,放在同一个文件夹中(或者同一个目录中区去),原因很简单:因为会生成类文件的,而我们的 windows 的在同一个文件夹中不可存放两个同名的文件的

类的编写

先编写一个结构简单的类看看,步骤如下:

  • 在Java中我们使用 关键字 class 声明一个类,
  • 给类起一个见名知意的名字,首字母大写,遵循大驼峰的命名原则
  • 编写类的特征,特征即类的属性部分又称为(字段)
  • 编写类的函数(方法),即类的成员方法

public class Person {
//    类的属性,字段
    int age;       // 年龄
    String name;   // 姓名
    
//    方法(行为),成员方法
    public void study() {
        System.out.println("青,取之于蓝,而胜于蓝,冰,水为之,而寒于水。");
    }
}

类的实例化 (对象的创建和使用)

  • 到这里,问你一个问题,你有对象吗?呵呵
  • 如果没有,没关系,我们来 new 出一个对象
  • 使用 new 运算符创建的类类型的“主体”,称为实例 ,创建实例的操作称为实例化
  • 类的实例,数组的主体统称为 对象 ,类的实例和数组的主体都是使用 new 动态创建的,所谓的对象,就是对程序运行时动态创建的主体的总称。

  • 在编写好以后,我们就可以创建对应类的对象了,使用 new 运算符,然我们来,new 一个对象吧,格式如下:
类名  对象名 = new 类名( );


public class Person {
//    类的属性,字段
    int age;       // 年龄
    String name;   // 姓名

//    方法(行为),成员方法
    public void study() {
        System.out.println("青,取之于蓝,而胜于蓝,冰,水为之,而寒于水。");
    }

    public static void main(String[] args) {
        Person person = new Person(); // 创建对象,实例化,new 一个对象
    }
}


在这里插入图片描述


字段,方法 的访问

  • 给对象的属性赋值:
对象名.属性名 =;
  • 调用对象中的方法:
对象名.方法名( );
  • 使用 . (逗号) 运算符;访问对象中的字段,以及方法

  • 这里的**“访问”** 既包含读,也包含了写

  • 对于没有赋予初值的字段,有默认初始值

    • 默认值规则:

      • 对于各种数值类型,默认值为 0,和 0,0
      • 对于 boolean 类型,默认值为 false
      • 对于引用类型 ( String , Arrays ,自定制类),默认值为 null
  • null 在 Java 中表示 “空引用” ,表示不引用任何对象,类似于C语言中的空指针,如果对 null 进行,. 的操作会引起异常



class Person {
//        类的属性,字段
    int age;       // 年龄
    String name;   // 姓名

//       方法(行为),成员方法
    public void study() {
        System.out.println("青,取之于蓝,而胜于蓝,冰,水为之,而寒于水。");
    }
}
public class Main {
    public static void main(String[] args) {
        Person person = new Person(); // 创建对象,实例化,new 一个对象
        person.name = "你好世界";
        person.age = 18;
        System.out.println("name:"+person.name);
        System.out.println("age:"+person.age);
        person.study();
    }
} 


  • 结果:

在这里插入图片描述


未初始化的字段(成员变量)

  • 默认值规则:
    • 对于各种数值类型,默认值为 0,和 0,0
    • 对于 boolean 类型,默认值为 false
    • 对于 char 类型,默认值为 ;\u0000
    • 对于引用类型 ( String , Arrays ,自定制类),默认值为 null

class BeginNum {
    char cNum;
    int iNum;
    float fNum;
    boolean bNum;
    String str;
}

public class Main {
    public static void main(String[] args) {
        BeginNum  beginNum = new BeginNum(); // 实例化,new创建一个对象
        System.out.println("cNum:"+beginNum.cNum);
        System.out.println("iNum:"+beginNum.iNum); // 0
        System.out.println("fNum:"+beginNum.fNum); // 0.0
        System.out.println("bNum:"+beginNum.bNum); // false
        System.out.println("sNum:"+beginNum.str);  // null
    }
}

  • 结果:

在这里插入图片描述


类中的内存视图:



class Person1 {
    String name;
    int age;

    public void show() {
        System.out.println("我叫"+name+age+"岁");
    }
}
public class Main {
    public static void main(String[] args) {
        Person1 person1 = new Person1();
        person1.age = 18;
        person1.name = "小华";
        person1.show();
    }
}

对应的内存分析图:


在这里插入图片描述


static 关键字

  • 这里简单的使用
  • 修饰属性
  • 修饰方法
  • 修饰代码块
  • 修饰类
  • 这里我们先学习修饰属性,和方法

类变量

  • 类变量类类型变量 是不一样的,请注意它们的含义,不要混淆了。
  • 类变量: 的另一个名字就是静态字段
  • 类类型变量:我们自己对于描述复杂对象,创建的类型
静态字段 和 非静态字段
静态字段
  • static修饰的的字段,是类变量,也叫静态字段
  • 同一个类的实例之间共享的数据的静态字段,即类变量
  • 只要在字段声明时加上,static 关键字,就可以实现,共享,由于类中共享的变量,因此被称为类变量。另外,由于声明时加上了static ,因此也被称为静态字段
  • 注意:Java静态属性和类相关,和具体的实例无关,换句话说。同一个类的不同实例共用同一个静态属性,再换句话说:就是被 static 关键字修饰的字段,不是属于各个实例的数据,而是属于类的所有实例共享的数据
  • static 修饰的字段——静态字段,是和类一起被加载到内存的,只会加载一次到内存中,所有实例化(对象)一起共用它这一个
  • 静态字段的访问格式:
类名.静态字段名 =;

非静态字段
  • 这个简单,不被 static 关键字修饰的字段,就被称为非静态关键字
  • 非静态关键字是和对象相关的,所以每个实例化对象中的非静态字段是私有的,不一样的,不同的对象对应各自的非静态字段,
  • 是非静态字段是在实例化(对象)后,才会加载到内存中的,比静态的慢

class Test {
    int num;         // 非静态字段
   static int count; // 静态的字段
}
public class Main {
    public static void main(String[] args) {
        Test test1 = new Test();
        test1.num++;
        Test.count++;
        System.out.println("test1:"+test1.num);  // 1
        System.out.println("count:"+Test.count); // 1
        /* 静态的字段的访问方式: 类名.静态字段*/

        Test test2 = new Test();  // 实例化两个对象
        test2.num++;
        Test.count++;
        System.out.println("test2:"+test2.num);  // 1
        System.out.println("count"+Test.count);  // 2
    }
}

  • 结果:

在这里插入图片描述


  • 我们可以通过结果可以看到 非静态的字段,在不同的对象中各自相互独立的,互补干扰
  • 而静态的则是所有实例化对象共有的

类方法

  • 同样的被 static 修饰的方法,静态方法又称为:类方法

非静态方法 和 静态方法
  • 同静态字段一样的,所以这里就详细介绍了

静态方法
  • static 关键字修饰的方法,叫做类方法,又称 静态方法
  • 同样静态方法,和类有关,是和类一起加载到内存的,只会加载一次,与所有实例共用该方法
  • 可以直接调用方法,而无需创建类的实例
  • 不过这里好像并不常用的
  • 调用静态方法的格式:
类名.静态方法名( );

非静态方法
  • 同理,不被 static 关键字修饰的方法,可以称为非静态方法

  • 同样非静态方法,和实例化对象有关,在实例化后,非静态方法,才被加载到内存当中去的


class Demo {
    public static void test() {
        System.out.println("静态方法");
    }
}
public class Main {
    public static void main(String[] args) {
//        调用静态方法 类名+静态方法名
        Demo.test();
    }
}

  • 结果:

在这里插入图片描述


静态 与 非静态 有趣关联

  • 被关键字 static 修饰的方法,字段,称为 静态方法

  • 没有被关键字 static 修饰的方法,字段称为:非静态方法

  • 静态 与 非静态 有趣关联

    • 静态之间可以相互访问(类名+静态方法,类名+静态属性),但是静态的不可以直接访问非静态的,如果非要访问的话,要实例化,再通过对象引用才可以访问非静态的,不然会报错的。
    • 非静态之间可以相互访问,以及还可以直接访问静态的
    • 简单的说明一下原因:
      • 前面我说过:静态的是和类一起加载到内存的,非静态的是实例化后,才被加载到内存当中的,这里可以看出静态的是比非静态的先加载到内存当中的,而我们静态的访问非静态的时候,非静态的还没有加载到内存中(也就是还没有创建起来) ,我们就是在访问一个还没有加载到内存中的数据(未创建的数据),而我们的程序都要加载到内存中才能运行的,我们 Java中的 JVM 虚拟机是不会允许这样的事情发生的 ,直接暴力点,给你来个报错.
      • 想要详细了解的,请移步到这里:Java 中为什么静态的无法访问非静态的

  • 非静态的访问,静态以及非静态的方法,属性的实例


class Demo {
    int num1 = 10;
    static int num2 = 100;

    public void test1() {
        System.out.println("num1:"+num1); // 非静态之间可以互相访问
        System.out.println("num2:"+num2); // 非静态的可以访问静态的属性
        System.out.println("非静态方法");
        test2();     // 非静态可以直接访问静态的方法
    }

    public static void test2() {
        System.out.println("静态方法");
    }
}
public class Main {
    public static void main(String[] args) {
        Demo demo = new Demo(); // new 实例化对象
        demo.test1();
    }
}

  • 结果:

在这里插入图片描述


  • 静态的访问 静态,以及非静态的

在这里插入图片描述

在这里插入图片描述



小结:
class Person {
//        类的属性,字段
    int age;       // 年龄
    String name;   // 姓名
    String sex;
    public static int count; // 类变量也叫静态变量,编译时已经产生了,属于类本身,且只有一份,存放在方法区中
    public final int SIZE = 10; // 被final 修饰的叫常变量,不是静态的,也属于对象,后续不可以更改的
    
    public static final int COUNT = 99; // 静态常量,属于类本身,只有一份,被final 修饰,后续不可更改
    
//    实例成员方法
    public void eat() {
        int a = 10; // 局部变量
        System.out.println("eat()!");
    }
    
//    实例成员方法
    public void sleep() {
        System.out.println("sleep()!");
    }
//    静态成员方法
    public static void staticTest() {
/*静态成员不能访问非静态成员
        sex = "mua"; error
*/
        System.out.println("staticTest()!");
    }
}
public class Main {
    public static void main(String[] args) {
        Person person = new Person(); // 产生对象,实例化对象
        System.out.println(person.age);
        System.out.println(person.name);
        System.out.println(Person.COUNT); // 类变量的访问:类名+属性名(方法名)
        System.out.println(Person.count);
        person.eat();
        person.sleep();
    }
}

  • 结果:

在这里插入图片描述


  • 内存图示:

在这里插入图片描述


private 实现封装

  • 类的使用者 和 类的调用者
  • private / public 这两个关键字表示**”访问权限的控制“**
  • public 修饰的成员变量或者成员方法,公开的可以直接被类的调用者使用
  • private 修饰的成员变量或者成员方法,不能被类的调用者使用,只能在本类中调用使用

直接使用public


class Person3 {
    public String name = "小华";
    public int age = 18;
}
public class Main {
    public static void main(String[] args) {
        Person3 person3 = new Person3(); // 产生对象,实例化对象
        System.out.println("我叫"+person3.name+"今年"+person3.age+"岁");
    }
}

  • 结果:

在这里插入图片描述


private 封装

  • 通过 pricvate 封装将属性进行私有化,
  • 再编写公有方法,利用 public 进行修饰,提供属性对应的设置和获取方法
  • 再赋值方法中根据实际需求进行合理的限制,提高代码的安全性

在这里插入图片描述

在这里插入图片描述


class Person2 {
    private String name = "小华";  // private 只能再本类中可以被访问到
    private int age = 18;   // private 只能再本类中可以被访问

    public void show() { // public 公有的一个接口,通过该接口,访问被 private私有化的属性
        System.out.println("name:"+name);
        System.out.println("age:"+age);
    }
}
public class Main {
    public static void main(String[] args) {
        Person2 person2 = new Person2();
/*        System.out.println(person2.name); // 报错无法访问,private的属性
        System.out.println(person2.age);  // private 修饰的属性,只能在对应的类中访问*/
        person2.show();
    }
}

  • 结果:

在这里插入图片描述


getter(获得) / setter(设置) 方法

  • private 不光能修饰字段,也能修饰方法
  • 通常情况下,我们会把字段设为private 属性,但是方法是否需要设为 public ,就需要看具体情形而定,一般我们希望一个类只提供必要的public 方法,而不应该把所有的方法都无脑的设为 public
  • 当我们使用private 来修饰字段的时候,就无法直接使用这个字段了
  • 使用:
    • getter 方法,表示获取这个成员的值:的一个统称
    • setter 方法,表示设置这个成员的值:的一个统称
  • 不是所有的字段都一定要提供 setter / getter 方法 ,而是根据实际情况决定提供那种方法,有的时候是 setter 和 getter 一起使用的
  • IDEA 中可以使用 Alt + Insert (或者 Alt _ F12 ) 快速生成 **setter / getter ** 方法,在VSCode 中可以使用鼠标右键 ——> 菜单——> 源代码操作 中自动生成 setter / getter 方法

  • 操作:同时按 键盘中的 Alt+ Insert 键,弹出左边的窗口:

  • 选择其中的 **Getter and Setter **, 或者你只需要其中的某一个,选中它,点击一下

  • 还可以鼠标右键——> 弹出下面右边的窗口图 ——> 点击其中的 ——> Generate ——> 弹出和下面左边的图的窗口是一致的

]
在这里插入图片描述


在这里插入图片描述


  • 最后点击 OK 就会自动帮你生成你需要的 setter / getter 方法

class Person6 {
    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;
    }

    private String name;
    private int age;

}
public class Main {
    public static void main(String[] args) {
        Person6 person6 = new Person6();
        person6.setName("你好世界");
        person6.setAge(18); // 设置
        String name = person6.getName();
        int age = person6.getAge(); // 获取
        System.out.println(name);
        System.out.println(age);
    }
}

  • 结果:

在这里插入图片描述


  • 注意事项:
  • 上述代码中的 getName 和 getAge 方法就是 getter 方法,表示获取这个成员的值
  • 上述代码中的 setName 和 setAge 方法就是 setter 方法,表示设置这个成员的值

this. 关键字

  • this. 关键字指代对象自身,通过this. 关键字可以指向自身地址空间,简要内存分析如下图:

在这里插入图片描述

  • 这里我们现在只是简单的使用该 关键字中的其中的一个作用:
  • this. 修饰属性,可以在本类中访问自身属性
  • ==this.==表示当前对象引用(注意不是当前对象). 可以借助 this 来访问对象的字段和方法.
  • 要习惯用上this. 关键字,大大提高代码的可读性

class Person10 {
    private String name;
    public void setName(String name) {
        name = name;
    }
    public String getName() {
        return name;
    }
}
public class Main {
    public static void main(String[] args) {
        Person10 person10 = new Person10();
        person10.setName("你好世界");
        System.out.println(person10.getName());
    }
}

  • 结果:

在这里插入图片描述


  • 上述代码:我们明明赋值了,可显示的结果确实 null (空),为什么?
  • 我们来分析一下下面的代码:
   public void setName(int name) {
        name = name; 
       /*注意:问题出现在这里,我们不能对于当形参,与我们的属性名字相同时
       ,其意义就被改变了,name = name 这是在给自己赋值,name这里成了一个局部变量,局部变量优先原则,代表的就是 局部变量自己赋值给自己了,而局部变量,出了作用域,释放空间了,并没有达到我们属性赋值的效果,*/
       /* 解决方案:
       使用关键字 (this.)表示当前对象引用(注意不是当前对象),是引用,可以借助this.来访问对象的字段和方法,
*/
    }

  • 解决方法:
class Person10 {
    private String name;
    public void setName(String name) {
        this.name = name; // 注意这里:(this.)表示引用当前对象,name 赋值的就不再是自身局部变量了,而是该对象中的属性;
    }
    public String getName() {
        return name;
    }
}
public class Main {
    public static void main(String[] args) {
        Person10 person10 = new Person10();
        person10.setName("你好世界");
        System.out.println(person10.getName());
    }
}

  • 结果:

在这里插入图片描述


  • 当在类中,我们的形参在命名上与类中的属性,发生冲突时,可是,我们一般希望我们在 setter 方法中的形参都是与 类的属性名是一致的,这样可以减少我们命名上的苦恼,命名一致可读性又非常高,但命名一致就会发生冲突(局部变量化),基于这么多的好处,我们可以使用this. 关键字,就可以避免这样的冲突问题。
  • this. 关键字指代对象自身,表示引用当前自身对象
  • 是不是非常 nice ,嘿嘿,这只是this. 关键字的冰山一角,后面我会一一讲清楚的。

最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家!后会有期,江湖再见!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值