自学内容网 自学内容网

【Java 基础】类和对象(构造&this&封装&static&代码块)

✨                                                  风起于青萍之末,浪成于微澜之间       🌏 

📃个人主页island1314

🔥个人专栏:java学习

⛺️  欢迎关注:👍点赞 👂🏽留言 😍收藏  💞 💞 💞


 

目录

🚀引言

1. 类定义和使用及实例化

1.1 创建类的语法

1.2 创建具体的对象(实例化)

1.3 范例🌰

2. 构造方法

2.1 定义构造方法

2.2 构造方法重载

3. this 关键字

3.1 this关键字调用当前对象的成员变量

3.2 this关键字调用当前对象的方法

3.3 注意事项

4. 封装

4.1 访问限定符

4.2 封装扩展之包

🥝包的概念

🥑导入包中的类

🍉自定义包

5. static 关键字

5.1 static修饰成员变量

5.2 static修饰成员方法

5.3 static成员变量初始化

6. 代码块

6.1 普通代码块

6.2 构造代码块

6.3 静态代码块

7. 扩展知识

 7.1 匿名对象

7.2 对象的打印

📖总结



🚀引言

在Java中一切皆对象,一切都围绕对象进行,找对象、建对象,用对象等。

类:把具有相同属性和行为的一类对象抽象为类。类是抽象概念,如人类、犬类等,无法具体到每个实体。

对象:某个类的一个实体,当有了对象后,这些属性便有了属性值,行为也就有了相应的意义。

类是描述某一对象的统称,对象是这个类的一个实例而已。有类之后就能根据这个类来产生具体的对象。其中类对象所具备的共同属性和行为(方法)都在类中定义。比如:描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了。

1. 类定义和使用及实例化

1.1 创建类的语法

class ClassName {
成员变量/ 实例变量;
成员方法;
}

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

1.2 创建具体的对象(实例化)

用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象

类名称 引用名称 = new 类名称()

Person per = new  Person();

  这个对象的引用   对象(在堆中储存)

(相当于给对象起了个名字)(所有类的对象都是引用数据类型)

注意事项:

  1. new 关键字用于创建一个对象的实例.
  2. 使用:  来访问对象中的属性和方法.
  3. 同一个类可以创建对个实例.

1.3 范例🌰

下面创建一个Animal 类的对象:

class Animal {
    String name;
    int age;

    void eat(String name) {
        System.out.println(name + "正在吃");
    }
    void show() {
        System.out.println("name:" + name + ",age:" + age);
    }
}

public class Test {
    public static void main(String[] args) {
        Animal dog = new Animal();
        dog.show();
        dog.name = "小黄";
        dog.age = 18;
        dog.show();
    }
}

💢💢输出如下:

注:

  1. 在Java中一个源文件(*.java)只可以存在一个主类(public class),而且public修饰的类必须要和文件名相同,main方法所在的类一般要使用public修饰
  2. 类的命名规则:使用有意义的大驼峰单词命名法,每个单词的首字母都要大写
  3. 类中定义的成员变量都有默认值
  4. 关于引用数据类型的特殊值 null:null在Java中表示“空引用”,即只有名字,没有任何对内存中的地址,如果直接使用值为null的引用,去操作(使用.操作符)任何属性或者方法(成员变量、成员方法),都会报错。  如:空指针异常

2. 构造方法

2.1 定义构造方法

构造方法(也称为构造器)是一个特殊的成员方法,使用关键字new实例化新对象时会被自动调用, 用于完成初始化操作。在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。

new 执行过程

  • 为对象分配内存空间(空间大小由该类中成员变量的属性决定)
  • 调用对象的构造方法为对象成员变量赋值(当构造方法调用结束后,该对象初始化完成)

在使用时需要注意以下几点:

  1. 方法名称必须与类名相同
  2. 没有返回值类型,设置为void也不行
  3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
  4. 如果类中没有提供任何的构造函数,那么编译器会默认生成一个不带有参数的构造函数。若类中定义了构造方法,则默认的无参构造将不再生成。
  5. 构造方法可以重载,规则和普通方法的重载一致 (用户根据自己的需求提供不同参数的构造方法)

注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。

 下面定义了一个Animal 的一个无参构造:

class Animal {
    String name;
    int age;

    public Animal(){
        System.out.println("无参构造");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
    }
}

2.2 构造方法重载

 构造方法是为了类中的成员变量赋值的,此时的重载只可能是参数的个数不同。

class Animal {
    String name;
    int age;

    public Animal(){
        System.out.println("无参构造");
    }
    public Animal(String s,int x){
        name = s;
        age = x;
        System.out.println("带两个参数的构造");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal1 = new Animal();
        Animal animal2 = new Animal("蛙",19);
    }
}

注:不能用一个实例化对象去调用它的构造方法?

      原因:构造方法就是去产生对象,如果用构造方法产生的对象去调用产生它的构造方法,就相当于自己又在自己的构造方法(这样就变成了我生我自己)

3. this 关键字

3.1 this关键字调用当前对象的成员变量

在了解了构造之后,我们先来看一个例子:

class Animal {
    String name;
    int age;

    public Animal(String name,int age){
        name = name;
        age = age;
        System.out.println("带两个参数的构造");
    }
    void show() {
        System.out.println("name:" + name + ",age:" + age);
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal2 = new Animal("蛙",19);
        animal2.show();
    }
}

输出如下: 

疑问:为什么我们已经通过构造方法给成员变量初始化了,但输出结果仍是默认值呢?

      原因:形参名称与成员变量名称相同。程序设计理念:就近匹配原则,编译器会找最近的相同名称的变量在哪

那么我们该如何解决上面这个问题了,就需要用到 this 关键字

修改如下:

public Animal(String name,int age){
   this.name = name;
   this.age = age;
   System.out.println("带两个参数的构造"); 
}

3.2 this关键字调用当前对象的方法

① 调用普通的成员方法

class Animal {
    String name;
    int age;

    public Animal(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("带两个参数的构造");
    }

    void show() {
        System.out.println("name:" + name + ",age:" + age);
    }
    //show()方法是成员方法,必须通过对象调用
//this表示对象的引用,调用成员方法时不写,编译时也会自动加上
    void func() {
        show(); // 相当于 this.show()
        System.out.println("成员方法调用");
    }
}

💢 这个我们后面可以用在特殊场景下当成员方法被private修饰,我们就可以在类中新写一个函数,来调用。

② 构造方法的相互调用

 若不同参数的构造方法之间出现了重复的调用,可以使用 this(参数)调用其他的构造方法。

class Animal {
    String name;
    int age;

    public Animal(){
        System.out.println("无参构造");
    }
    public Animal(String name){
        this();
        this.name = name;
    }
    public Animal(String name,int age){
        /*this.name = name;
        this.age = age;*/
        this(name);
        System.out.println("带两个参数的构造");
    }
}

3.3 注意事项

① this调用其他的构造方法必须放在当前构造方法的首行

② this调用构造方法不能成环(避免构造方法就死循环了)

③ this关键字表示当前对象的引用

(当前是通过哪个对象调用的属性或者方法,this就指代此对象)

class Animal {
    String name;
    int age;

    void fun(){
        System.out.println(this);
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal1 = new Animal();
        System.out.println(animal1);
        animal1.fun();
    }
}

输出如下: 

注:前面的Note.Test1 是该文件所在的文件夹。(也就是下面将会提到包的概念)

4. 封装

面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。何为封装呢?我们该文中主要讲到的就是 封装 这一概念。

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

4.1 访问限定符

作用:访问权限用来控制方法或者字段能否直接在类外使用

【Java提供的四个访问限定符号如下】

权限修饰符:在Java中,权限修饰符指的是所修饰的属性、方法或者类可见的范围有多大。

范围protecteddefaultprotectedpublic
同一包中的同一类✔️✔️✔️✔️
同一包中的不同类✔️✔️✔️
不同包中的子类✔️✔️
不同包中的非子类✔️

【说明】

  • protected主要是用在继承中,继承部分详细介绍
  • default权限指:什么都不写时的默认权限
  • 访问权限除了可以限定类中成员的可见性,也可以控制类的可见性

封装有很多表现形式,private实现属性和方法的封装只是其中一种。

注:private 关键字不能直接修饰一个类(外部类)如:private class A

💢原因:定义类是为了产生对象,让外部使用的。若用 private 关键字封装此类,则外部根本不知道此类的存在,更不用提使用对象了,就和我们的目的产生矛盾。

4.2 封装扩展之包

🥝包的概念

为了更好的管理类,把多个类收集在一起成为一组,称为软件包。

比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件下,也可以对某个文件夹下的音乐进行更详细的分类。

🍎🍎在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。

🥑导入包中的类
  • 使用 import语句导入包.
  • 可以使用import static导入包中静态的方法和字段
/*import java.util.*; 表示只要是 util下的所有类都可以适配
 ,但是我们更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况*/
import java.util.Arrays;
import java.util.Date; // 导入包中的 Date类,使用时: Date date = new Date();


// import static 能够导入一些静态方法,
//如下:
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
    double x = 30;
    double y = 40;
    // 静态导入的方式写起来更方便一些.
    // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
    double result = sqrt(pow(x, 2) + pow(y, 2));
    System.out.println(result);
    }
}

 🍐🍐注:import 和 C++ 的 #include 差别很大,C++ 必须 #include 来引入其他文件内容,但是 Java 不需要,import 只是为了写代码的时候更方便,import 更类似于 C++ 的 namespace 和 using

🍉自定义包

基本规则

  • 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
  • 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如  com.zxj.demo1 ).
  • 包名要和代码路径相匹配. 例如创建  com.zxj.demo1 的包, 那么会存在一个对应的路径  com/zxj/demo1 来存储代码
  • 如果一个类没有 package 语句, 则该类被放到一个默认包中.

 常见的包

  1.  java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2.  java.lang.reflect:java 反射编程包;
  3.  java.net:进行网络编程开发包。
  4.  java.sql:进行数据库开发的支持包。
  5.  java.util:是java提供的工具程序包。(集合类等) 非常重要
  6.  java.io:I/O编程开发包。

5. static 关键字

5.1 static修饰成员变量

static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。

【静态成员变量特性】

  1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
  2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
  3. 类变量存储在方法区当中
  4. 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)

class Animal {
    String name;
    int age;
    static String sex;

    public Animal(){

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

    void show() {
        System.out.println("name:" + name + ",age:" + age + ",sex:" + sex);
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal1 = new Animal("小黄",18);
        Animal animal2 = new Animal();
        animal1.show(); animal2.show();
        animal1.sex = "wsz"; //通过对象访问
        Animal.sex = "未知"; //直接类名访问
        animal1.show(); animal2.show();
    }
}

 输出如下:

注意:

  • Animal.sex = null;

 上面这样写并不会报空指针异常:static属性称为类属性,通过类名称直接访问,此时没有对象也能调用(包含该类的null引用)

不能在方法中定义一个static变量

🍅原因:在方法中定义的变量是局部变量,在栈中存储,而 static变量是在方法区中存储,若要在方法中定义一个static变量就会产生矛盾,因为一个变量不可能既在栈中存储,又在方法区中存储。

拓展知识:

若在类中定义了一个常量,通常情况下都会把static 和 final 共同使用,称为类的常量

比如:

class P {
    final int age = 18;//成员常量,在堆中存储,必须在定义时就赋值
    static String school = "北大"//静态变量,在方法区中存储,所有 P 类的对象共享
}

(因为age属于成员常量,P 类中的所有对象都有age这个属性,且值都是18——>天然的共享概念,将它定义为static final,所有 P 类的对象共享这个属性,全局唯一。(既节省空间,有对应共享语义)) 

全局常量的命名规则:所有单词全部大写,多个单词使用下划线分隔

static final String UNIVERSITY = "剑桥";

5.2 static修饰成员方法

被static修饰的成员方法称为静态成员方法,是类的方法不是某个对象所特有的

【静态方法特性】

  1. 不属于某个具体的对象,是类方法
  2. 可以通过对象调用,也可以通过类名.静态方法名(…)方式调用,更推荐使用后者
  3. 不能在静态方法中访问任何非静态成员变量
  4. 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用
  5. 静态方法无法重写,不能用来实现多态

注:

成员方法能否访问静态变量和静态方法

🍍必须通过对象访问的方法去调用,不需要对象就可以访问的变量和方法,逻辑通过static方法只能调用静态变量和静态方法等,static家族的成员可以相互调用(都属于静态域)

5.3 static成员变量初始化

注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性
静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。

  1. 就地初始化
    就地初始化指的是:在定义时直接给出初始值
  2. 静态代码块初始化
    那什么是代码块呢?继续往后看 😃 ~~

6. 代码块

使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:

  • 普通代码块
  • 构造块
  • 静态块
  • 同步代码块(这个涉及到多线程部分,暂时不讲)

6.1 普通代码块

定义在方法中的代码块。

public class Main{
    public static void main(String[] args) {
        { //直接使用{}定义,普通方法块
            int x = 10 ;
            System.out.println("x1 = " +x);
        }
        int x = 100 ;
        System.out.println("x2 = " +x);
    }
}

这种用法一般较少见

6.2 构造代码块

定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。注:构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行。

class Animal {
    String name;
    int age;
    {
        System.out.println("Animal类的构造代码块");
    }

    public Animal(){
        System.out.println("Animal类的无参构造");
    }

}

public class Test {
    public static void main(String[] args) {
        Animal a1 = new Animal();
        Animal a2 = new Animal();
    }
}

输出如下: 

6.3 静态代码块

 使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。注:无论产生多少对象,只会执行一次,且静态代码块优先于构造块执行。

class Animal {
    String name;
    int age;
    {
        System.out.println("Animal类的构造代码块");
    }

    public Animal(){
        System.out.println("Animal类的无参构造");
    }

    static {
        System.out.println("Animal类的静态代码块");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal a1 = new Animal();
        Animal a2 = new Animal();
    }
}

输出如下: 

注意事项:

① 主类中的静态代码块优先于主方法执行。(JVM要执行主方法,首先要加载主类,主类一加载,静态块就执行了)

public class Test {
    static {
        System.out.println("主类的静态代码块");
    }
    public static void main(String[] args) {
        System.out.println("进入主方法");
    }
}

输出如下: 

② 静态变量存在于方法区中,类定义时就会有初始值(在以下代码中,初始值为10),类此时在方法区中。但此时类只是定义了,还没被加载。当主方法中使用了该类时,就需要把该类从方法区加载到内存中。类加载后,静态代码块就被执行了(x = 10——> x = 100)

class St{
   static int x = 10;
   static  {
       x = 100;
        System.out.println("St类的静态代码块");
    }
    public St(){
        System.out.println("St类的无参构造");
    }
}
public class Test {
    public static void main(String[] args) {
        St st = new St();
        System.out.println(st.x);
    }
}

输出如下: 

总结:

  • 静态代码块不管生成多少个对象,其只会执行一次
  • 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
  • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
  • 实例代码块只有在创建对象时才会执行

7. 扩展知识

 7.1 匿名对象

匿名只是表示没有名字的对象.

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

new出来的对象,没有引用指向,使用一次后就被JVM销毁。常用于测试类中的某些功能。   如 :new Person();

代码示例:

class Person {
    private String name;
    private int age;
    public Person(String name,int age) {
        this.age = age;
        this.name = name;
    }
    public void show() {
        System.out.println("name:"+name+" " + "age:"+age);
    }
}
public class Main {
    public static void main(String[] args) {
        new Person("cc",19).show();//通过匿名对象调用方法
    }
}
// 执行结果
name:cc age:19

7.2 对象的打印

   当一个引用类型的变量调用println函数打印时,默认输出的都是引用类型的地址。(不是真正的内存地址,Java中程序员是无法知道任何确认的内存地址)

正常情况下:

class St{
    int x;
    public St(int x){
        this.x = x;
    }
}
public class Test {
    public static void main(String[] args) {
        System.out.println(new St(12));
        System.out.println(new St(14));
    }
}

 在类中构造一个toString()方法,对象默认调用此方法进行打印。

 注意事项:

  • toString 方法会在 println 的时候被自动调用.
  • 将对象转成字符串这样的操作我们称为 序列化.
  • toString 是 Object 类提供的方法, 我们自己创建的 Person 类默认继承自 Object 类, 可以重写 toString 方法实现我们自己版本的转换字符串方法. (关于继承和重写这样的概念, 我们后面会重点介绍)
  • @Override 在 Java 中称为 "注解", 此处的 @Override 表示下面实现的 toString 方法是重写了父类的方法. 关于注解后面的课程会详细介绍.
  • IDEA快速生成Object的toString方法快捷键:alt+f12(insert)


📖总结

  • 一个类可以产生无数的对象,类就是模板,对象就是具体的实例。
  • 类中定义的属性,大概分为几类:类属性,对象属性。其中被static所修饰的数据属性称为类属性, static修饰的
  • 方法称为类方法,特点是不依赖于对象,我们只需要通过类名就可以调用其属性或者方法。
  • 静态代码块优先实例代码块执行,实例代码块优先构造函数执行。
  • this关键字代表的是当前对象的引用。并不是当前对象。

💞 💞 💞那么本篇到此就结束,希望我的这篇博客可以给你提供有益的参考和启示,感谢大家支持!!!祝大家天天开心


原文地址:https://blog.csdn.net/island1314/article/details/141780802

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!