Java的数据类型,一些鲜为人知的细节概述2

Java的数据类型,一些鲜为人知的细节概述

Java的数据类型可以分成两大类:

  • 基本数据类型

    • 整型 byte,short,int,long

    • 浮点型 float,double

    • 字符类型 char

    • 布尔类型 boolean

  • 引用数据类型

    • 数组

    • 接口

这节主要是补充 Java的引用数据类型。
一、类

1、类的定义

  • 具有相同属性和行为的对象可以抽象为类

  • 类是一个封装了数据(属性)和操作这些数据的方法的模版

  • 类定义了对象的结构和行为

2、类的组成

  • 属性:指事物的特征,静态描述,例如:手机有品牌,价格,尺寸

  • 行为:指事物所具有的功能,动态描述,例如:手机可以打电话,也可以

    发短信。

3、类的理解

  • 类是现实世界中具有相同事物的抽象集合。

  • 类是对象的模版,对象是类的具体体现;或者,类是对象的抽象,对象是类的实例。

  • 类是对象的数据类型,类是具有相同属性和行为的一组对象的集合。

  • 简单理解:类就是对现实事物的一种描述。

4、类的声明

  • 类的声明通常包括关键字class,后跟类名。

  • 类名通常首字母大写,遵循驼峰命名规则。

  • 类体包含属性(成员变量)和方法(成员方法)。

  • 补充:驼峰命名法

    • 如果只有一个单词全小写‘

      例如:display() sum()

    • 如果多个单词构成,则第一个单词全小写,后续单词首字母大写

      例如:sayHello() getMax() findStudentById()

public class Person {
     private String name; // 成员变量
     private int age;
 ​
     // 构造器
     public Person(String name, int age) {
         this.name = name;
         this.age = age;
     }
 ​
     // 方法
     public void sayHello() {
         System.out.println("Hello, my name is " + name);
     }
 ​
     // 获取器(getter)
     public String getName() {
         return name;
     }
 ​
     // 设置器(setter)
     public void setName(String name) {
         this.name = name;
     }
 }

5、类的特性

  • 成员变量:类中的变量,用于存储对象的状态

  • 方法:类中的方法,用于定义对象的行为

  • 构造器:特殊的方法,用于初始化新创建的对象

  • 访问修饰符:public,protected,private,default(没有明确指定时,默认访问级别)

  • 继承:类可以继承另一个类的属性和方法

  • 多态:子类可以覆盖父类的方法,从而实现不同的行为

  • 封装:隐藏对象内部的实现细节,只暴露必要的接口给外部使用

  • 抽象类:可以包含抽象方法的类,不能被实例化

  • 接口:定义了行为的标准,可以被类实现

6、类的使用

  • 实例化:创建类的实例,即对象。

  • 创建对象格式:

    类名 对象名 = new 类名();

    调用成员格式:

    对象名.成员变量

    对象名.成员方法() ;

    示例:

    public class Person {
         private String name; // 私有成员变量
         private int age;
     ​
         // 默认构造器
         public Person() {
         }
     ​
         // 参数化构造器
         public Person(String name, int age) {
             this.name = name;
             this.age = age;
         }
     ​
         // 获取器(getter)
         public String getName() {
             return name;
         }
     ​
         // 设置器(setter)
         public void setName(String name) {
             this.name = name;
         }
     ​
         // 获取器(getter)
         public int getAge() {
             return age;
         }
     ​
         // 设置器(setter)
         public void setAge(int age) {
             this.age = age;
         }
     ​
         // 方法
         public void sayHello() {
             System.out.println("Hello, my name is " + name);
         }
     ​
         // 重写 toString 方法
         @Override
         public String toString() {
             return "Person{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     '}';
         }
     }
     ​
     public class Main {
         public static void main(String[] args) {
             Person person = new Person("John Doe", 30);
             person.sayHello();
             System.out.println(person);
     ​
             // 使用 setter 修改属性
             person.setName("Jane Doe");
             System.out.println(person.getName());
         }
     }
     /*
     在这个示例中,我们定义了一个 Person 类,它包含了私有成员变量 name 和 age,以及相应的 getter 和 setter 方法。此外,还有一个 sayHello 方法和重写的 toString 方法,用于打印对象的信息。
     */

7、对象内存布局

  • 栈内存:存放局部变量和对象的引用

  • 堆内存:存放对象本身

  • 方法区:存放类的元数据,如类名、方法名、常量池等

示例:

Person person = new Person("John Doe", 30);
  • 解析:person是一个局部变量,存放在栈内存中

  • new Person("John Doe", 30)创建了一个新的Person对象,该对象存放在堆内存中。

  • person指向堆内存中的Person对象。

总结:

  • 系统会为每个对象开辟单独的内存空间(堆空间),用来存储对象的属性。

  • 类的成员方法存储在方法区,只保留一份,只要是该类的对象,都可以调用。

8、变量对比

1)静态变量:在类中声明且使用static关键字修饰的变量。

  • 生命周期:随着类的加载而存在,随着类的加载而消失

  • 存储位置:方法区

2)成员变量(实例变量)、局部变量的区别

  • 定义位置不同

    成员变量:类中方法外

    局部变量:方法内部或方法声明上(形参列表)

  • 内存中位置不同

    成员变量:堆内存

    局部变量:栈内存

  • 生命周期不同

    成员变量/实例变量:随着对象的存在而存在,随着对象的消失而消失。

    局部变量:随着方法的调用而存在,随着方法的调用完毕而消失。

  • 初始化值不同

    成员变量/实例变量:有默认初始化值

    局部变量:没有默认初始化值,必须先定义、赋值才能使用

二、接口

Java中接口是引用数据类型的一种,它定义了一组方法的签名,而不提供具体的实现,接口在Java中扮演着非常重要的角色,特别是实现多态性和扩展性方面。

1、接口的概述

  • 接口是对Java单继承的补充,接口是Java中一种重要的抽象机制,它提供了一种定义行为规范和实现多态性的方式。

  • 接口最终也会被编译成 .class文件,但是一定要明确接口并不是类,而是另一种引用数据类型。

2、接口的定义

  • 接口是一个完全抽象的类,它包含零个或多个抽象方法。

  • 使用interface关键字定义接口。

  • 接口中的方法不需要方法体,即不需要{};

  • 接口中的方法默认是公共的(public)和抽象的(abstract),是抽象方法。

    例如:public abstract void move(); 也可以简化为:void move();

  • 接口中的数据成员默认是是公共的 (public)、静态的 (static) 和最终的 (final)。是常量,名称一般全大写。

    例如:public static final int NUM = 10;也可以简化为:int NUM = 10(等价)

 public interface Drawable {
     void draw(); // 抽象方法
     int MAX_SIZE = 100; // 常量
 }

3、接口的实现

  • 类可以通过实现接口来提供接口中方法的具体实现。

  • 一个类可以实现多个接口,这解决了Java中类只能单一继承的问题。

  • 在实现接口时,类必须提供接口中所有抽象方法的具体实现,除非该类本身也声明为抽象类。

public class Circle implements Drawable {
     @Override
     public void draw() {
         System.out.println("Drawing a circle.");
     }
 }

注意事项:

  • 接口属于引用数据类型的一种,它不是类,它没有构造方法。

  • 接口的实现类(子类),可以是正常类(重写所有抽象方法),也可以是抽象类(包含抽象方法)。

  • 接口不能创建对象,一般用接口引用指向实现类对象。

  • 在类和接口的实现关系中,可以使用多态,因为类和接口的实现关系,可以理解为继承的一种形式。

4、接口的继承

  • 接口可以继承其它接口(多继承)。

  • 接口继承使用extends关键字。

  • 一个接口可以继承多个其他接口。

 public interface Shape extends Drawable {
     void resize(int percent);
 }

5、接口的使用

  • 通过接口引用指向实现接口的类的对象

  • 接口支持多态性,可以使用接口类型的引用指向不同实现类的对象。

 public class InterfaceDemo {
     public static void main(String[] args) {
         Drawable drawable = new Circle();
         drawable.draw(); // 输出 "Drawing a circle."
 ​
         Shape shape = new Circle();
         shape.resize(50); // 假设 Circle 类实现了 resize 方法
     }
 }

注意事项:

  • 接口多态应用时,编译看左边,运行看右边。

  • 即接口引用只能调用接口中包含的方法,成功调用的是重写以后的方法。

JDK8及以后的变化

  • 默认方法:从Java 8 开始,接口可以包含具有默认实现的方法,这些方法使用default关键字声明。

  • 静态方法:从Java 8 开始,接口可以包含静态方法,这些方法使用static关键字声明。

  • 增强了接口的功能

 public interface Drawable {
     void draw();
 ​
     default void defaultMethod() {
         System.out.println("This is a default method.");
     }
 ​
     static void staticMethod() {
         System.out.println("This is a static method.");
     }
 }

综合完整实例:

 public interface Drawable {
     void draw(); // 抽象方法
     int MAX_SIZE = 100; // 常量
 ​
     default void defaultMethod() {
         System.out.println("This is a default method.");
     }
 ​
     static void staticMethod() {
         System.out.println("This is a static method.");
     }
 }
 ​
 public class Circle implements Drawable {
     @Override
     public void draw() {
         System.out.println("Drawing a circle.");
     }
 }
 ​
 public class Square implements Drawable {
     @Override
     public void draw() {
         System.out.println("Drawing a square.");
     }
 }
 ​
 public class InterfaceDemo {
     public static void main(String[] args) {
         Drawable drawable = new Circle();
         drawable.draw(); // 输出 "Drawing a circle."
         drawable.defaultMethod(); // 输出 "This is a default method."
 ​
         Drawable.staticMethod(); // 输出 "This is a static method."
 ​
         drawable = new Square();
         drawable.draw(); // 输出 "Drawing a square."
     }
 }
 ​
 /*
 在这个示例中,我们定义了一个 Drawable 接口,它包含了一个抽象方法 draw() 和一些其他特性。然后,我们定义了两个类 Circle 和 Square,它们实现了 Drawable 接口,并提供了 draw() 方法的具体实现。最后,在 main 方法中,我们展示了如何使用接口类型的引用指向不同的实现类的对象,并调用它们的方法。
 */

三、数组

1、数组概述

  • 数组是一个容器,用于存储固定数量的同类型元素

  • 数组中的每个元素可以通过索引访问,索引从0开始

  • 数组的长度是固定的,一旦创建后不能改变

  • 数组可以存储基本数据类型或引用数据类型

2、数组的定义

  • 数组类型[] 数组名;(推荐使用)

    int [] arr; char[] arr;
  • 数组类型 数组名[];

    int arr[]; double arr[];
  • 注意:

    数组是引用数据类型,用来存储一个引用值(可以理解为地址值)

    数组没有进行初始化,不可以直接使用

3、数组初始化

定义数组(开辟栈空间内存)的同时,给其赋上初值,就叫做数组的初始化。

  • 静态初始化:

    数组的长度,取决于{}中元素列表的长度

    数据类型[] 数组名 = new 数据类型 []{元素列表}

     int[] numbers = new int[]{1, 2, 3, 4, 5}; // 初始化
  • 特殊写法 (简化写法)不能把声明和赋值拆开写

    数据类型[] 数组名 = {元素列表};

     int[] numbers = {1, 2, 3, 4, 5}; // 直接初始化
  • 动态初始化:

    数据类型[] 数组名 = new 数据类型[数组长度];

    注意事项:

    • 数组中是有元素的。从物理意义上来讲

    • 数组中的元素内容是不可能为空(整整意义上的无),任意时刻其实都是有值的。

    • 当我们用动态初始化的方式创建数组时,数组中所有的元素位置都会被该数据类型的默认值填充

    •  int[] arr1 = new int[3];
       double[] arr2 = new double[2];
       String[] arr3 = new String[4];

注意:

  • new 是一个关键字,表示为数组开辟内存空间

  • 等号两边的数据类型要一致(先记住,后期会补充不一致的情况)

  • 数组长度必须要有,可以>=0(一般大于0),但不能为负数

4、数组下标和长度

  • 数组的下标的区间为[0, 数组长度 - 1]

  • 如果数组的长度为length,那么数组下标的最小值为0,下标最大值为length-1

  • 数组长度,是指在一个数组中,可以存放同一类型元素的最大数量

  • 获取数组长度固定格式: 数组名.length

     int[] arr = new int[4];
     System.out.println(arr.length);

    注意:

    • 数组长度,必须在创建数组对象的时候就明确指定

    • 数组长度,一旦确定,就无法改变

    • 数组长度,可以>=0(一般大于0),但不能为负数

5、数组异常

  • 索引越界:数组下标超出范围

    程序运行后,将会抛出 ArrayIndexOutOfBoundsException 数组越界异

    常。

    解决方案:将错误的索引修改为正确的索引范围即可!

  • 空指针:

    arr = null;这行代码意味着变量arr将不再保存数组的内存地址,我们通过arr这个标识符再也找不到对空间数组异常,因此运行的时候会抛出NullPointerException空指针异常。

    解决方案:给数组一个真正的堆内存空间引用即可。

6、二维数组

Java中的二维数组是一种特殊的一维数组,其中的每个元素本身也是一个一维数组。二维数组可以被视为表格或矩阵的形式,通常用于存储多维数据。下面详细介绍Java中二维数组的定义、初始化、访问和一些常见用法。

1)二位数组的概述

二位数组可以看作是一个数组的数组,其中每个元素又是一个一维数组。二维数组非常适合表示表格或矩阵形式的数据。

2)定义二维数组

  • 数据类型 数组名[][];
  • 数据类型[][] 数组名;

3)创建二维数组

  • 数据类型 数组名 = new 数据类型行数[行数][列数];
  • 数据型 数组名 = new 数据类型行数[行数][];
    for (int i = 0; i < 行数; i++) {
    
        数组名[i] = new 数据类型[列数];
    
    }

4)初始化二维数组

数据类型[][] 数组名 = new 数据类型[行数][列数];
   for (int i = 0; i < 行数; i++) {
       for (int j = 0; j < 列数; j++) {
           数组名[i][j] = 值;
       }
   }

5)访问二维数组元素

  • 数组名行索引

  • 二维数组的遍历

 public class Demo{
     public static void main(String[] args){
         //定义并创建二维数组
         int[][] arr = new int[3][4];
         
         //使用嵌套循环初始化二维数组
         for(int i = 0;i < arr.length;i++){
             for(int j = 0;j < arr.length; j++){
                 arr[i][j] = i * 10 + j;
             }
         }
         //访问二维数组中的元素
         System.out.println(arr[1][2]);
         
         //遍历二维数组并打印所有元素
         for(int i = 0;i < arr.length; i++){
             for(int j = 0;j < arr.length; j++){
                 System.out.print(arr[i][j] + " ");
             }
             System.out.println();
         }
     }
 }

6)二维数组的长度

  • 获取行数:

    int rows = 数组名.length;

  • 获取列数:

    int columns = 数组名[行索引].length;

 下一节将更新冒泡排序、二分查找、选择排序、插入排序、希尔排序..

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ice_葡萄多多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值