面向对象高级(三)

面向对象高级(三)

一、内部类

内部类:类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。

内部类有四种形式,分别是成员内部类、静态内部类、局部内部类、匿名内部类。

1.1 成员内部类

成员内部类就是类中的一个普通成员,类似于成员变量、成员方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Outer {
private int age = 99;
public static String a="黑马";

// 成员内部类
public class Inner{
private String name;
private int age = 88;

//在内部类中既可以访问自己类的成员,也可以访问外部类的成员
public void test(){
System.out.println(age); //88
System.out.println(a); //黑马

int age = 77;
System.out.println(age); //77
System.out.println(this.age); //88
System.out.println(Outer.this.age); //99
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}
}

创建对象格式:

1
2
3
4
//外部类.内部类 变量名 = new 外部类().new 内部类();
Outer.Inner in = new Outer().new Inner();
//调用内部类的方法
in.test();

总结一下内部类访问成员的特点

  • 既可以访问内部类成员、也可以访问外部类成员
  • 如果内部类成员和外部类成员同名,可以使用**类名.this.成员**区分

1.2 静态内部类

在成员内部类的前面加了一个static关键字。静态内部类属于外部类自己持有。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Outer {
private int age = 99;
public static String schoolName="黑马";

// 静态内部类
public static class Inner{
//静态内部类访问外部类的静态变量,是可以的;
//静态内部类访问外部类的实例变量,是不行的
public void test(){
System.out.println(schoolName); //99
//System.out.println(age); //报错
}
}
}

需要使用外部类的类名调用。

1
2
3
//格式:外部类.内部类 变量名 = new 外部类.内部类();
Outer.Inner in = new Outer.Inner();
in.test();

1.3 局部内部类

是定义在方法中的类,和局部变量一样,只能在方法中有效。

局部内部类的局限性很强,一般在开发中是不会使用的。

1.4 匿名内部类

匿名内部类是一种特殊的局部内部类;所谓匿名,指的是程序员不需要为这个类声明名字

1
2
3
4
new 父类/接口(参数值){
@Override
重写父类/接口的方法;
}

匿名内部类 本质上 时一个没有名字的子类对象、或者接口的实现类对象,

只有在调用方法时,当方法的形参是一个接口或者抽象类,为了简化代码书写,而直接传递匿名内部类对象给方法。

二、枚举

2.1 枚举类

1
2
3
public enum 枚举类名{
枚举项1,枚举项2;
}

其实枚举项就表示枚举类的对象,只是这些对象在定义枚举类时就预先写好了,以后就只能用这几个固定的对象。.

2.2 场景

枚举一般表示一组信息,然后作为参数进行传输。

我们现在有这么一个应用,用户进入应用时,需要让用户选择是女生、还是男生,然后系统会根据用户选择的是男生,还是女生推荐不同的信息给用户观看。

1665670887179

这里我们就可以先定义一个枚举类,用来表示男生、或者女生

1
2
3
public class Constant{
BOY,GRIL
}

再定义一个测试类,完成用户进入系统后的选择

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test{
public static void main(String[] args){
//调用方法,传递男生
provideInfo(Constant.BOY);
}

public static void provideInfo(Constant c){
switch(c){
case BOY:
System.out.println("展示一些信息给男生看");
break;
case GRIL:
System.out.println("展示一些信息给女生看");
break;
}
}
}

最终再总结一下枚举的应用场景:枚举一般表示几个固定的值,然后作为参数进行传输

三、泛型

3.1 泛型

在定义类、接口、方法时,同时声明了一个或者多个类型变量(如:),称为泛型类、泛型接口、泛型方法、它们统称为泛型。

ArrayList集合的设计者在定义ArrayList集合时,就已经明确ArrayList集合时给别人装数据用的,但是别人用ArrayList集合时候,装什么类型的数据他不知道,所以就用一个<E>表示元素的数据类型。

3.2 自定义泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//定义一个泛型类,用来表示一个容器
//容器中存储的数据,它的类型用<E>先代替用着,等调用者来确认<E>的具体类型。
public class MyArrayList<E>{
private Object[] array = new Object[10];
//定一个索引,方便对数组进行操作
private int index;

//添加元素
public void add(E e){
array[index]=e;
index++;
}

//获取元素
public E get(int index){
return (E)array[index];
}
}

四、常用API

4.1 Object类

Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法。

  • toString():调用toString()方法可以返回对象的字符串表示形式

    在Student类重写toString()方法,那么我们可以返回对象的属性值,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Student{
    private String name;
    private int age;

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

    @Override
    public String toString(){
    return "Student{name=‘"+name+"’, age="+age+"}";
    }
    }
  • euqals(Object o):判断此对象与参数对象是否”相等”

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Test{
    public static void main(String[] args){
    Student s1 = new Student("赵薇",23);
    Student s2 = new Student("赵薇",23);

    //equals本身也是比较对象的地址,和"=="没有区别
    System.out.println(s1.equals(s2)); //false
    //"=="比较对象的地址
    System.out.println(s1==s2); //false
    }
    }

    但是如果我们在Student类中,把equals方法重写了,就按照对象的属性值进行比较

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class Student{
    private String name;
    private int age;

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

    @Override
    public String toString(){
    return "Student{name=‘"+name+"’, age="+age+"}";
    }

    //重写equals方法,按照对象的属性值进行比较
    @Override
    public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Student student = (Student) o;

    if (age != student.age) return false;
    return name != null ? name.equals(student.name) : student.name == null;
    }
    }
  • clone()方法:某一个对象调用这个方法,这个方法会复制一个一模一样的新对象,并返回。

    想要调用clone()方法,必须让被克隆的类实现Cloneable接口。如我们准备克隆User类的对象,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class User implements Cloneable{
    private String id; //编号
    private String username; //用户名
    private String password; //密码
    private double[] scores; //分数

    public User() {
    }

    public User(String id, String username, String password, double[] scores) {
    this.id = id;
    this.username = username;
    this.password = password;
    this.scores = scores;
    }

    //...get和set...方法自己加上

    @Override
    protected Object clone() throws CloneNotSupportedException {
    return super.clone();
    }

    public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
    User u1 = new User(1,"zhangsan","wo666",new double[]{99.0,99.5});
    //调用方法克隆得到一个新对象
    User u2 = (User) u1.clone();
    System.out.println(u2.getId());
    System.out.println(u2.getUsername());
    System.out.println(u2.getPassword());
    System.out.println(u2.getScores());
    }
    }
    }

    上面演示的克隆方式,是一种浅克隆的方法,浅克隆的意思:拷贝出来的对象封装的数据与原对象封装的数据一模一样(引用类型拷贝的是地址值)

    深拷贝:对象中基本类型的数据直接拷贝,对象中字符串数据拷贝的时地址,其他对象,不会拷贝地址,会创新新对象。

4.2 Objects类

提供了一些方法可以对任意对象进行操作。

1665760840329

4.3 基本类型包装类

Java中有一句很经典的话,万物皆对象。Java中的8种基本数据类型还不是对象,所以要把它们变成对象,变成对象之后,可以提供一些方法对数据进行操作。

1665758797003

  • 创建包装类对象

    1
    2
    3
    4
    Integer a = new Integer(10);
    Integer b = Integer.value(10);
    Integer c = 10; //自动装箱
    int d = c ;//自动拆箱
  • 包装类数据类型转换

    • 把字符串转换成数值型数据:

      public static int parseInt(String s)

    • 把数值型数据转换成字符串:

      public static String valueof(int a)


面向对象高级(三)
https://wendyflv.github.io/2024/10/29/JAVASE——面向对象高级(三)/
作者
Wendyflv
发布于
2024年10月29日
许可协议