对象数组,封装的实现,return的用法,构造器(构造方法),继承的实现和特点,this和super的使用,重写和重载的区别(十)

253 阅读11分钟

对象数组

1.数组的定义:

​ 数组是用来存储一组相同数据类型的数据,使用统一的名称来管理它,每一个元素使用编号进行区分,这个编号称为下标,每一个数据称呼为元素,元素的总个数称为数组的长度

2.数组元素的数据类型:

(1)基本数据类型:例如:int[]

(2)引用数据类型:例如:String[],Student[],Circle[],如果元素是引用数据类型,那么我们称为对象数组。因为每一个元素存储的是对象

3.数组可以分为:

​ (1)一维数组

​ (2)二维数组

​ 二维数组可以堪称元素类型是以为数组的以为数组,例如int[][],可以看成元素是int[]的一维数组。

​ (3)三维数组等,理论上是可以的,但是几乎没有用过。

4.如何声明对象数组?

元素的数据类型[] 数组名;

5.对象数组的初始化

(1)静态初始化

​ 元素的数据类型[] 数组名 = {........};

(2)动态初始化

​ 数组名 = new 元素的数据类型[长度];

动态初始化后,元素还未赋值,此时还是默认值,引用数据类型默认是null。

//静态初始化
String[] strings = {"hello","java"};
Student[] students = {stu1,stu2,...};
//动态初始化
String[] strs = new String[5];
Student[] stus = new Student[5];

6.数组的使用

(1)获取数组的长度

数组名.length;

(2)获取某个元素的方式

数组名[下标];
//下标的范围[0,数组名.length-1];
//如果超过下标范围会报ArrayIndexOutOfBoundsException数组下标越界

(3)元素的赋值

数组名[下标] = 对象;

(4)遍历

for(int i = 0;i < strings.length;i++){
	System.out.println(strings[i]);
}

7.通过对象数组的元素,访问对象的成员

public class TestPlus {
    public static void main(String[] args) {
        //声明并创建一个长度为5的矩形对象数组
        Rectangle[] array = new Rectangle[5];

        //创建5个矩形对象
        /*array[0] = new Rectangle();
        array[1] = new Rectangle();
        ...
        */
        for (int i = 0; i < array.length; i++) {
            array[i] = new Rectangle();
        }

        //为矩形对象的成员赋值
        //5个矩形对象的长分别是10,20,30,40,50
        //5个矩形对象的宽分别是5,15,25,35,45
        //array[0]为什么可以.length?
        // 因为array[0]是一个矩形类型的变量,对象,它能.出什么,看它类型
        //array[0]现在是Rectangle类型,可以.出Rectangle中声明的成员。
//        array[0].length = 10;
//        array[0].width = 5;
        for (int i=0; i<array.length; i++){
            array[i].length = (i+1)*10;
            array[i].width = (2*i+1)*5;
        }

        //遍历输出结果
        for(int i=0; i<array.length; i++){
            //System.out.println("长:" + array[i].length + ",宽:" + array[i].width +",面积:" + array[i].area() +",周长:" + array[i].perimeter());
            System.out.println(array[i].getInfo());
        }
    }
}
class Rectangle{//矩形
    double length;
    double width;

    public double area(){//面积
        return length * width;
    }
    public double perimeter(){//周长
        return 2 * (length + width);
    }

    public String getInfo(){
        return "长:" + length + ",宽:" + width + ",面积:" + area() +",周长:" + perimeter();
    }
}

8.对象数组的内存分析

![对象数组内存分析](F:\Typora File by Myself\对象数组内存分析.png)

封装

1.为什么要进行封装?

(1)考虑数据的安全性;

(2)隐藏细节;

(3)方便;

2.如何实现封装?(狭义,可见性范围的限制)

可以给属性加修饰符,例如:private

private:私有的,表示仅限于本类中使用

可见性修饰符:

本类本包的其他类中其他包的子类其他包的非子类
private可见不可见不可见不可见
default(缺省)可见可见不可见不可见
protected可见可见可见不可见
public可见可见可见可见(同一个工程任意位置可见)

对于类的成员(成员变量、成员方法等)来说,四种private,default(缺省),protected,public,但是对于外部的类来说,只能使用default(缺省)和public。

3.如果属性私有化,那么怎么对外提供方法来操作/访问它?

实际开发中,习惯上,属性(成员变量)都是私有化。然后提供get/set方法来访问它。

(1)set方法:用于给成员变量赋值的

//标准格式:
public void setXxx(数据类型 参数名){
	成员变量 = 参数名;
}

(2)get方法:用于获取成员变量的值

//标准格式:public 数据类型 getXxx(){	return 成员变量;}

注意:

(1)set/get 方法名有标准,set/get单词 + 成员变量名(并且把成员变量首字母大写)

(2)对于get方法,如果成员变量是boolean类型,一般把get换成is

(3)开发中,get/set方法可以由idea生成,快捷键Alt + Insert(有的电脑可能需要同时按下Fn)

4.this的一个用法

当成员变量与方法的局部变量(例如:形参)同名时,可以在成员变量前面加this来区别。

为什么我们会出现局部变量(例如:形参)与成员变量同名呢?

因为变量是标识符,标识符有一个命名规范,见名知意。

例如public void setRadius(double radius)方法的形参的作用,就是给radius半径赋值,因此使用radius再好不过了。

5.当静态变量对应的set方法中出现了,局部变量与静态变量同名时,需要使用”类名.变量名“来进行区分,此时不能使用this来区分。

成员变量分两种:静态变量和实例变量。

为什么静态方法中不允许出现this?

因为我们调用静态方法,通常(也建议)使用”类名.“来使用

而this本质上指代的是当前对象,也就是”this.变量名“相当于”对象.变量名“。

return总结:

1.用法有两种:

​ (1)return 返回值; //仅用在方法的返回值不是void的方法体中

​ (2)return ; //仅用在方法的返回值是void的方法体中。

2.意义

​ (1)return 返回值; //表示返回结果并结束

​ (2)return ;//表示不返回结果,只是结束当前循环

3.注意:

(1)如果方法有返回值,即返回值类型不是void,那么方法体中必须有return 返回值; 而且要求无论当前方法从哪个分支结束,都必须有一个return 返回值;语句

(2)如果方法没有返回值,即返回值类型是void,那么方法体中return ;语句是可选的。

构造器

1.什么是构造器?

​ 从名字来看,它是用来构造xxx的结构,它是类用来构造对象的结构。

在new后边调用的就是这个类的构造器。

作用:

(1)创建对象

(2)在创建对象时的成员变量初始化。

2.长什么样?如何自己定义/声明构造器?

【修饰符】 class 类名{//和一般的方法很像,但是它是没有返回值的,且构造器名和类名一致	【修饰符】 构造器名(){//无参的构造器}	【修饰符】 构造器名(形参列表){//有参的构造器}}

构造器与方法长得很像,又把构造器称为构造方法。

3.特点

(1)如果一个类没有声明任何构造器,那么编译器将会给这个类添加一个默认的无参(没有形参)构造方法。

(2)构造器的名称,必须与类名完全一致。

(3)构造器没有返回值类型,也不要写void,如果写上了,它就变成一个普通的方法。

(4)构造器是可以进行重载的。

​ 构造器的形式越多,创建对象方式的可选性越多。

(5)如果一个类声明了构造器,那么编译器就不会给他添加默认的无参构造了。

(6)构造器的修饰符:只能是private,缺省,protected,public(权限修饰符),其他的都不可以使用(比如说static、final)。

(7)如果一个类没有声明构造器,会自动添加一个无参构造器,这个构造器的修饰符默认与class前的修饰符一致。

(8)子类不会继承父类的构造器,但是必须在子类构造器的首行调用父类的构造器。

​ 默认调用的时父类的无参构造,也可以使用super();表示调用父类的无参构造器。

​ 如果父类没有无参构造,那么在子类构造器中要指明调用的是父类的哪一个有参构造器。

4.idea生成构造器的快捷键:Alt+Insert

继承

1.什么是继承?为什么要继承?

​ (1)在编程中需要复用代码,需要继承原来一些类。

​ (2)表示类与类之间的关系,is a的关系

​ (3)对原来的类进行”扩展“。

2.如何实现继承?

extend关键字

子类:继承别人的类叫做子类,也称为派生类,SubClass

父类:被继承的类叫做父类,也称为基类,超类 ,SuperClass

【修饰符】 class 子类 extends 父类{}

3.继承的特点

(1)Java只支持单继承,每一个子类都只能有一个直接父类。

(2)Java支持多层继承,父类的父类也是父类

(3)当然,一个Java的父类可以同时有多个子类。

(4)子类继承父类时不会继承父类的构造器,但是在子类的构造器中一定会”调用“父类的构造器。默认情况下,调用父类的无参构造器。如果父类没有无参构造器,那么需要使用super(...)调用父类的有参构造器。

父类的构造器是创建父类对象用的,那么不能继承到子类中。但是父类的成员变量会继承到子类中,在创建子类对象时,需要借助父类的构造器为这些成员变量初始化。

(5)子类会继承构造器以外的其他成员,比如成员变量、成员方法。但是,如果成员变量、成员方法的修饰符是私有的,那么在子类中不能直接使用,需要间接使用。如果成员变量、成员方法的修饰符是缺省的,那么跨包的子类中也不能直接使用。

(6)父类的静态变量和静态方法可以被继承到子类中,即可以通过子类的对象访问到该静态变量,但是静态方法不能被子类重写。

4.继承的特点之成员方法

(1)方法的重写(override)

​ 当子类继承了父类的成员方法后,如果父类的方法体实现不适合子类,那么子类可以选择重写。

(2)方法的重写有要求

①方法名必须相同

②形参列表必须相同

③返回值类型:

​ Ⅰ:父类方法的返回值类型是void和基本数据类型,那么子类方法必须与父类相同。

​ Ⅱ:父类方法的返回值类型是引用数据类型,那么子类方法的返回值类型可以是这个类,或者这个类的子类。

④权限修饰符:

​ Ⅰ:如果父类的方法的权限修饰符是private,那么子类是无法进行重写的,

如果父类是其他包的,并且方法的修饰符是缺省,那么子类也是无法进行重写的。

​ Ⅱ:其他情况下,重写方法的权限修饰符 可以大于等于被重写方法的权限修饰符

​ 本包中,父类的方法的修饰符是缺省的,子类的重写方法的修饰符可以是缺省的,protected,public ​ 其他包中,父类的方法的修饰符是protected,子类的重写方法的修饰符可以是protected,public ​ 其他包中,父类的方法的修饰符是public,子类的重写方法的修饰符可以是public

⑤其他修饰符

父类的static,final方法是不能重写的

(3)抛出异常时的要求

​ ①如果被重写方法没有throws编译时异常,那么重写方法时,就不能throws编译时异常

​ ②如果被重写方法throws编译时异常,那么重写方法时,只能throws该异常类型或该异常类型的子类。<=

​ ③如果被重写方法throws运行时异常,子类重写时,可以一样,可以不写。(无关

​ ④如果被重写方法没有throws运行时异常,子类重写时,可以一样,可以throws自己的运行时异常。(无关

this和super

this关键字

1.this单词的意思:当前对象

2.this可以出现在哪里?

(1)构造器中:this表示正在new的对象。

(2)非静态方法中:this表示调用这个方法的对象。

(3)非静态代码块中

3.this不能出现在?

(1)静态方法中

(2)静态代码块中

因为这两个位置都没有对象

4.使用形式有三种

(1)this.成员变量

​ 当成员变量与局部变量同名时,可以使用this.表示成员变量。

(2)this.成员方法

​ 没有必须用的情况。

​ 如果用的话,表示调用当前对象的xx方法。

​ 如果不用this的话,一般这个方法是本类声明的,如果在本类中没有找到,会找从父类继承的可见的成员方法。

(不用this时,默认先找本类,在找父类)。

(3)this()或this(实参列表)//这里是没有点.的

​ this():表示调用本类的无参构造;

​ this(实参列表):表示调用本类的有参构造;

this()或this(实参列表)必须在构造器的首行,这两个只能使用其中一个。

例如:无论通过哪一个构造器,我都希望它能打印一句”hello“

super关键字

1.super单词的意思:表示父类的

2.可以出现在哪里?

(1)构造器中:super表示调用父类的xx。

(2)非静态方法中:super表示调用父类xx。

(3)非静态代码块中

3.super不能出现在?

(1)静态方法中

(2)静态代码块中

因为这两个位置都没有对象

this和super这两个关键字和静态无缘,即都不能出现在静态的xx结构中。

3.使用前提:super要引用到父类的xx(xx可以是父类的成员变量、成员方法、构造器),xx必须在子类是可见的。

4.使用形式

(1)super.成员变量

​ 当子类声明了与父类同名的成员变量时,可以使用super.来区分父类成员变量和子类成员变量。

​ 但是!在开发过程中,不要在子类中声明与父类同名的变量,会降低程序可读性。

(2)super.成员方法(重要)

​ 当子类,重写了父类的方法时,又想要在子类中访问父类的这个方法时,可以使用super。

(3)super()或super(实参列表)

super():表示调用直接父类的无参构造,完全可以省略这句话,因为不写,默认也是找父类的无参构造。

super(实参列表):表示调用直接父类的有参构造函数。

super()或super(实参列表)也必须在构造器首行。

注意:

this()或this(实参列表)只在本类找,如果本类没有找到对应的就报错了。

super()或super(实参列表)只在父类找。父类找不到就报错了。

重写和重载

重载:发生在同一个类中,出现了方法名相同,形参列表不同的多个方法,和返回值类型无关。

重写:是子类对继承的父类的方法进行重写,

​ 要求:方法名相同,形参列表,返回值类型(基本数据类型和void:相同,引用数据类型:小于等于),权限修饰符(大于等于,被重写的方法不能是private,跨包不能是缺省),其他修饰符(不能是final和static)