Java学习12

本文详细解读了Java中Object类的toString方法,介绍了如何覆盖该方法以实现更友好的对象转换为字符串。同时讨论了内部类(包括匿名内部类)、数组(一维、二维和动态初始化)以及栈的使用,展示了Java数组和数据结构的相关概念。
摘要由CSDN通过智能技术生成

Object类的toString方法

概述

Object类是所有类的祖宗类,它提供的方法是所有类都适用的,我们可以通过看它的源码来得知有什么方法。

其中的大部分都是以";"结尾的,中间带有native关键字的方法,表示的是底层调用C++写的dll程序(了解)。

其中有两个方法:`equals()`和`toString()`是可以调用的,这里重点了解`toString()`。

toString()方法

public static toString(){
    return getClass().getName() + "@" + Integer.toHexString(hashCode);
}
这是一个实例方法,需要先创建对象再调用方法,得到的是`类名@对象在堆内存里的内存地址`。

这个地址是内存地址通过哈希算法得出的十六进制结果,了解就好~

但其实,直接输出引用对象,出来的地址也是这个显示格式,因为它默认调用了`toString()`方法。

覆盖toString()方法

toString()是将对象转换为字符串,Java给定的默认方法在部分情况的调用是不尽如人意的,就比如说要输出年月日:

public class MyDate {
    private int year;
    private int month;
    private int day;
    public MyDate(){
        this(2023,1,21);
    }
    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public int getYear() {
        return year;
    }
    public void setYear(int year) {
        this.year = year;
    }
    public int getMonth() {
        return month;
    }
    public void setMonth(int month) {
        this.month = month;
    }
    public int getDay() {
        return day;
    }
    public void setDay(int day) {
        this.day = day;
    }
}
public class test02 {
    public static void main(String[] args) {
        MyDate myDate = new MyDate();
        System.out.println(myDate);
    }
}

image.png
这个结果很明显不是我们想要的,我们希望的是它能直接输出日期,这时候就需要对该方法进行方法重写。

public String toString(){
        return this.year+"年" +this.month+"月"+this.day+"日";
}

这样子就可以实现输出年月日了。
当然,实际开发中还存在着各种各样的需求,此时我们应该根据需求去对已有方法进行覆盖,使它服务于需求。

其实不覆盖也可以,但是由于多态的存在,使方法覆盖和多态联系在一起,所以说最好习惯方法覆盖

内部类

概述

定义:在一个类的内部定义的类,称为内部类。
分类:

  1.  实例内部类:类似于实例变量。
  2. 局部内部类: 类似于局部变量。
  3.  静态内部类:类似于静态变量。
  4.  匿名内部类: 内部类的一种。

使用内部类编写的代码可读性很差,实际开发中很少用,在这里只重点学习匿名内部类,便于之后能看懂这类代码。

匿名内部类

定义: 这个类没有名字,故称为匿名内部类。

public class MyMath {
    public void mySum(Computer c ,int x,int y){
        int retValue = c.sum(x,y);
        System.out.println(x+"+"+y+"="+retValue);
    }
}
interface Computer {
    int sum(int a,int b);
}
public class classDemo {
    public static void main(String[] args) {
        MyMath mm = new MyMath();
        mm.mySum(new Computer(),100,200);
    }
}
很明显,对于这个接口,是不能直接创建一个对象去传入mySum方法中,需要创建一个实现类:
public class ComputerImpl implements Computer{
    public int sum(int a,int b){
        return a+b;
    }
}
但是,我们可以通过匿名内部类来实现这个接口,这样的类是没有名字的!
public class classDemo {
    public static void main(String[] args) {
        MyMath mm = new MyMath();
        mm.mySum(new Computer(){
            public int sum(int a,int b){
        		return a+b;
    		}
        },100,200);
    }
}
这里表面上看好像是接口可以被创建对象了,实则不然,后面的`大括号{}`代表了对接口的实现!!!

不建议使用匿名内部类,因为这个类没有名字,不能重复使用,并且这么写太乱,可读性太差!

数组

之前学过数组,这里是接着之前的内容学的,跳过了前面的一维数组的基础知识

一维数组的扩容

在Java开发中,数组确定就无法改变,但是可以通过扩容来实现增长数组长度满足需求。
实质:重新创建一个新的更大的数组,将原有数组拷贝过去。
数组扩容效率较低,涉及数据拷贝问题,在以后的开发时候
注意
:尽可能少的进行数据扩容,在创建数组对象的时候就要估计数组的长度,避免进行数组扩容。

一维数组的数据拷贝

Java提供了一个用于数组拷贝的方法:
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
这里面五个参数从左往右分别代表:拷贝源,拷贝源起始下标,目标,目标起始下标,拷贝的数组长度。

基本数据类型和引用数据类型都是可以拷贝的~

二维数组

概述

二维数组其实是一个特殊的一维数组,特殊在这个一维数组中的每一个元素都是一个一维数组。
二位数组的静态初始化:
int[][] array ={{1,2,3},{4,5},{6,7,8,9}};

三维数组就相当于是每个元素里都是一个二维数组。

二维数组的动态初始化:int[][] array = new[3][4]

length属性

一维数组有几个元素就长度就是多少,二维数组是有多少个一维数组,长度就是多少。与数组中的一维数组内的数据无关!
如果想要取得二维数组中的一维数组的长度,需要表明一维数组的下标(以上面静态初始化数组为例):我们想要取得第一个数组的长度,需要标下标:a[0].length,其余类推即可。

元素访问&修改

案例:以上面静态初始化的二位数组为例,取出二维数组的第一个一维数组中的数据。

int[][] array ={{1,2,3},{4,5},{6,7,8,9}};
int[] a = array[0];//这是第一个一维数组!
int aa = a[0];//这是第一个一维数组里的第一个元素!
//也可以进行合并
int aa = array[0][0];

对于a[0][0]来说,前面两个是一个整体代表一维数组,之后再和后面的[0]结合为一个数组,代表着一维数组中的元素。
修改就是在访问二维数组的基础上进行一个赋值~

遍历

二维数组的遍历相比于一维数组的遍历,只需要多加一层循环,注意每一层循环的循环次数就可以了。

int[][] array ={{1,2,3},{4,5},{6,7,8,9}};
for (int i = 0; i < array.length; i++) {
    for (int j = 0; j < array[i].length; j++) {
        System.out.print("  "+array[i][j]);
    }
    System.out.println(" ");
}

动态初始化的二维数组的遍历也是一样的,只是给定了数组的长度,也可以通过直接方法得出数组的长度来实现,在没有赋予数据的时候默认值为0。

二维数组作为形参传递给方法

在传递的时候,只需要传递二维数组名就可以,如果不想新建一个变量,可以直接在传递的时候new一个数组,但是要保证该数组只使用一次!
sum(new int[][] {{1,2,3},{4,5},{6,7,8,9}});

总的来说,Java的数组和C语言的数组差距不大,只有格式上的区别~

每日一练

案例: 使用一维数组,模拟栈数据结构

  1. 这个栈可以存储Java中任何引用数据类型的数据。
  2. 在栈中提供push方法模拟压栈(栈满了需要有信息提示)。
  3. 在栈中提供pop方法模拟弹栈(栈空了也要有信息提示)。
  4. 编写测试程序,new栈对象,调用push、pop方法来模拟。
  5. 栈的初始化内存为10。
public class test {
    public static void main(String[] args) {
        MyStack stack = new MyStack();
        //压栈
        for (int i = 0; i <11; i++) {
            stack.push(new Object());
        }
        //弹栈
        for (int i = 0; i <11; i++) {
            stack.pop();
        }
    }
}
public class MyStack {
    private Object[] elements;
    //栈帧
    private int index = 0;

    public MyStack(Object[] elements) {
        this.elements = elements;
    }
    public MyStack(){
    //默认栈初始化容量是10
        this.elements = new Object[10];
        this.index = -1;
    }
    public void push(Object obj){
        if(this.index>=this.elements.length-1){
            System.out.println("压栈失败,栈已满!!!");
            return;
        }
        this.index++;
        this.elements[index]=obj;
        System.out.println("元素"+obj+"压栈成功,栈帧指向"+index);
    }
    public void pop(){
        if(index<0){
            System.out.println("弹栈失败,栈已空!!!");
            return;
        }
        System.out.print(elements[index]+"弹栈成功!!!");
        index--;
        System.out.println("栈帧指向"+index);
    }
}

image.png

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值