Java学习(6)初识二维数组、类的初认识

接上次博客:JAVA学习(5)(JVM内存划分、数组,由【数组的拷贝、数组的二分查找】等引出Java提供的Arrays类的应用,一些数组练习【多数元素、奇数排前偶数排后、找出单身狗等】)_di-Dora的博客-CSDN博客

 我们先简单回忆一下之前的一维数组:

一维数组也是一个引用变量。在Java中,数组属于引用数据类型,它们的变量存储的是数组对象的引用,而不是数组本身的值。

当我们声明一个一维数组时,实际上是在内存中开辟了一段连续的存储空间,用于存储数组元素的值。而数组变量本身存储的是指向该存储空间的引用,也就是数组对象的内存地址。

二维数组的定义

    public static void main4(String[] args) {
        //int[][] array1 = {1,2,3,4,5,6};  这样写是不被允许的
        int[][] array1 = {{1,2,3},{4,5,6}};
        //int[2][3] array1 = {{1,2,3},{4,5,6}}; 这样写也是不被允许的
        int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
        int[][] array3 = new int[2][3];//0
    }

二维数组的打印

怎么遍历二维数组?

    public static void main5(String[] args) {
        int[][] array1 = {{1,2,3},{4,5,6}};
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(array1[i][j]+" ");
            }
            System.out.println();
        }
    }

可是,当行和列很多的时候,我们怎么确定它们的数量呢?靠数数吗?肯定是不行的。

二维数组是特殊的一维数组,

 这样写:

System.out.println(array1[0]);
System.out.println(array1[1]);

这个时候应该输出的是地址:

那这样呢,是不是会把array1[0]和array1[1]的数组打印出来: 

        System.out.println(Arrays.toString(array1[0]));
        System.out.println(Arrays.toString(array1[1]));

 那长度呢?

        System.out.println("==========");
        System.out.println(array1[0].length);
        System.out.println(array1[1].length);
        System.out.println("==========");
        System.out.println(array1.length);

 

结果都一一验证了我们的猜想。

所以我们可以这样写:

   public static void main6(String[] args) {
        int[][] array1 = {{1, 2, 3}, {4, 5, 6}};
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                System.out.print(array1[i][j] + " ");
            }
            System.out.println();
        }
    }

如果使用 System.out.println((array1)) 来打印二维数组,输出的是数组的地址,因为这里的 array1 是一个引用类型,它指向二维数组的内存地址。而且,如果使用 Arrays.toString() 来打印二维数组,也只会输出二维数组的地址。 

那既然用

System.out.println(Arrays.toString(array1));

打印的是地址,怎么一次性地打印二维数组呢?

用深度打印: 

    public static void main(String[] args) {
        int[][] array1 = {{1, 2, 3}, {4, 5, 6}};
        System.out.println(Arrays.deepToString(array1));
        }

因为 deepToString() 方法可以处理多维数组,而 toString() 方法只能处理一维数组。

 不规则的二维数组

public static void main8(String[] args) {
    //不规则的二维数组
    int[][] array3 = new int[2][];
    array3[0] = new int[]{1,2,3};
    array3[1] = new int[]{4,5,6,7,8,9};
    System.out.println(Arrays.deepToString(array3));
}

即省略列数,可以让某一行的长度是不规则的。

  那么如果这样打印,会怎么样?

public static void main(String[] args) {
    //不规则的二维数组
    int[][] array3 = new int[2][];
/*    array3[0] = new int[]{1,2,3};
    array3[1] = new int[]{4,5,6,7,8,9};*/
    System.out.println(Arrays.deepToString(array3));
}

或者这样: 

    public static void main(String[] args) {
        //不规则的二维数组
        int[][] array1 = new int[2][];
        /*array3[0] = new int[]{1,2,3};
        array3[1] = new int[]{4,5,6,7,8,9};*/
        //System.out.println(Arrays.deepToString(array3));

        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                System.out.print(array1[i][j]+" ");
            }
            System.out.println();
        }
    }

出现了一个空指针异常: 

 

作为函数的参数:

1、参数传的是基本数据类型时,在方法中修改形参的值,不影响实参的值;

2、参数传数组类型(引用数据类型):在方法内部修改数组的内容,方法外部的数组内容也会发生改变。因为数组是引用类型,按照引用类型来进行传递,是可以修改其中存放的内容的。

总结:所谓的“引用“本质上只是存了一个地址,Java 将数组设定成引用类型,这样的话后续进行数组参数传参,其实只是将数组的地址传入到函数形参中,这样可以避免对整个数组的拷贝(数组可能比较长,那么拷贝开销就会很大)。


作为函数的返回值:
比如:获取斐波那契数列的前N项

public class TestArray {
    public static int[] fib(int n){
        if(n <= 0){
            return null;
        }
    int[] array = new int[n];
    array[0] = array[1] = 1;
    for(int i = 2; i < n; ++i){
        array[i] = array[i-1] + array[i-2];
    }
    return array;
}

注意事项:
1.一般一个文件当中只定义一个类

这样可以重命名一个类:

 这样可以直接同时修改类的名字和文件名。但是!这只适用于一个文件一个类的情况!!!

 

这样是不行的。2. main方法是程序的入口,它所在的类一般要使用public修饰(注意: Eipse默认会在public修饰的类中找main方法)

如上,每个类都可以有一个程序入口,它的左侧都有一个绿色三角,都可以run;               

3.public修饰的类必须要和文件名相同(每个文件一个public)

4.不要轻易去修改public修饰的类的名称,如果要修改,通过开发工具修改。

public class Test {
    public static void main(String[] args) {
        System.out.println("1234");
        //通过new关键字 实例化了一个Dog对象!
        Dog dog = new Dog();
        //dog就是一个引用 指向了Dog对象
        dog.name = "初一";
        dog.age = 10;
        dog.color = "黄色";
        System.out.println(dog.name);
        System.out.println(dog.age);
        System.out.println(dog.color);

        dog.eat();
        dog.bark();
        System.out.println("===========");
        Dog dog2 = new Dog();
        //dog就是一个引用 指向了Dog对象
        dog2.name = "初二";
        dog2.age = 12;
        dog2.color = "黄色2";
        System.out.println(dog2.name);
        System.out.println(dog2.age);
        System.out.println(dog2.color);

        dog2.eat();
        dog2.bark();

    }
}
class Dog {
    public String name;
    public int age;
    public String color;

    public void eat() {
        System.out.println("吃饭!");
    }

    public void bark() {
        System.out.println("汪汪叫!");
    }

    public static void main(String[] args) {
        System.out.println("fdsafasad");
    }

}

 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。换句话说,就是实例化出的对象才可以实际存储数据、占用物理空间。

public class Date {
    public int year;
    public int month;
    public int day;


    public void setDate(int y,int m,int d) {
        year = y;
        month = m;
        day = d;
    }

    public void printDate() {
        System.out.println("年:"+ year+" 月:" +month+" 日:"+day);
    }

    public static void main(String[] args) {
        Date date = new Date();
        date.setDate(2008,8,8);
        date.printDate();

    }

}

这样是没有问题的,改一下:

public class Date {
    public int year;
    public int month;
    public int day;


    public void setDate(int year,int month,int day) {
        year = year;
        month = month;
        day = day;
    }

    public void printDate() {
        System.out.println("年:"+ year+" 月:" +month+" 日:"+day);
    }

    public static void main(String[] args) {
        Date date = new Date();
        date.setDate(2008,8,8);
        date.printDate();
    }

}

这样就出问题了,一打印,结果全是0,相当于局部变量自己给自己赋值,局部变量优先。

这个时候,要么别同名,要么+this 

this引用的特性

1.this的类型;对应类类型引用,即哪个对象调用就是哪个对象的引用类型;
2this只能在”成员方法”中使用;
3.在“成员方法”中,this只能引用当前对象,不能再引用其他对象;
4.this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责调用成员方法;
对象的引用传递给该成员方法,this负责来接收。

    //代表当前对象的引用,建议大家习惯使用  this  谁调用了当前的set方法 谁就是this
    public void setDate(/*Date this,*/int year,int month,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public void printDate() {
        System.out.println("年:"+ year+" 月:" +month+" 日:"+day);
    }

那现在,我们增加一个对象,this该如何抉择?

    public static void main(String[] args) {
        Date date = new Date();
        date.setDate(2008,8,8);
        date.printDate();
        System.out.println("============");
        Date date2 = new Date();
        //setDate方法里面的this 就是谁调用过了这个方法
        date2.setDate(2009,9,9);
        date2.printDate();
    }

 不用担心!谁调用了当前的方法,谁就是this!

也就是说,其实下面的方法中都有一个隐藏的参数“ Date this ” :

public void setDate(/*Date this,*/int year,int month,int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
public void printDate(Date this) {
      System.out.println("年:"+ this.year+" 月:" +this.month+" 日:"+this.day);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值