Java学习笔记03 面向对象

1. 概述

面向对象是相对面向过程而言的。

  • 面向过程:强调功能、行为。
  • 面向对象:将功能封装进对象,强调具备了功能的对象。

简要的讲面向过程和面向对象的区别:
面向过程是一件事情“该怎么做”。
面向对象是一件事情“该让谁来做”。这个“谁”就是对象,它要如何完成任务是它的事情,调用者不需要知道。只需要最后一群对象最后合力把事情做好。

面向对象的三个特征:
1. 封 装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:将变化隔离;便于使用;提高重用性;安全性。
封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。
2. 继承
3. 多态

使用面向对象思想的程序开发过程就是要首先找对象来使用,如果没有,就自己创建对象。
找对象->建立对象->使用对象->维护对象的关系

面向对象的特点:

  • 将复杂的事情简单化。
  • 面向对象使开发人员由以前的执行者变成了指挥者。
  • 面向对象这种思想是符合人们思考习惯的思想。

2. 类和对象

类:对现实生活中事物的描述。
对象:就是这些事物中,实实在在存在的个体。

定义类的过程,就是在描述事物,就是在定义属性和方法。属性和行为共同成为类中的成员(成员变量和成员方法)。

1.成员变量

*成员变量和局部变量的区别:

  1. 成员变量直接定义在类中。局部变量定义在方法中,参数上,语句中。
  2. 成员变量在这个类中有效。局部变量只在自己所属的大括号内有效,大括号结束,局部变量失去作用域。
  3. 成员变量存在于堆内存中,随着对象的产生而存在,消失而消失。局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放。

通常成员变量前面会用private来修饰,如:

private int age;

被private修饰的成员即为私有成员,私有成员的访问权限最低,只有在本类中的访问有效,其他类不能直接创建对象来访问。所以只有通过本类提供的具体的访问方法来进行对私有成员的访问。这样做的好处在于可以在函数中加入对传入数据的判断等操作。属性是用于存储数据的,直接被访问,容易出现安全隐患,所以,类中的属性通常被私有化,并对外提供公共的访问方法。这个方法一般有两个,规范写法:对于属性 xxx,可以使用setXXX(),getXXX()对其进行操作。

2.构造函数

用于给对象进行初始化,是给与之对应的对象进行初始化,它具有针对性,是函数中的一种。其特点有:

  1. 该函数的名称与所在类的名称相同。
  2. 不需要定义返回值类型。
  3. 该函数没有具体的返回值。

所有对象在创建时,都需要初始化才能被使用。
一个类在定义时,如果没有定义过构造函数,那么该类中会自动生成一个空参数的构造函数,为了方便该类创建对象,完成初始化。如果该类中自定义了构造函数,那么默认的构造函数就没有了。

一个类中可以有多个构造函数,但是因为它们的函数名称都相同,所以只能通过参数列表来区分。所以,一个类中如果出现多个构造函数,则它们的存在是以重载体现的。

构造函数和一般函数的区别:

  1. 两个函数定义的格式不一样。
  2. 构造函数是对象被创建时,就被调用,用于对对象进行初始化,而且初始化的动作只执行一次。一般函数则是在对象创建后,需要调用才执行,可以被调用多次。

构造函数的使用:分析事物时,发现具体事务一出现,就会具备一些特征。那么将这些特征定义在构造函数内。
构造函数是可以私有化的,如果一个类的所有的构造函数全部都私有化,则代表该类不能创建对象。

构造函数的行为:
例如以下代码在执行创建一个对象时都在内存中做了什么事情?

Person p = new Person();
  1. 先将硬盘上指定位置的Person.class文件加载进内存。
  2. 执行main方法时,在栈内存中开辟了main方法的空间(压栈-进栈),然后在main方法的栈区分配了一个变量p。
  3. 在堆内存中开辟一个实体空间,分配了一个内存首地址值。new
  4. 在该实体空间中进行属性的空间分配,并进行了默认初始化。
  5. 对空间中的属性进行显示初始化。
  6. 进行实体的构造代码块初始化。
  7. 调用该实体对应的构造函数,进行构造函数初始化。()
  8. 将首地址赋值给p ,p变量就引用了该实体。(指向了该对象)

3.构造代码块

在类中的一段代码,形如:

class Demo
{
    {
        ...//构造代码块
    }

    Demo()//构造函数
    {
        ...
    }
}

构造代码块的作用是给对象进行初始化,一旦建立对象,构造代码块就会运行,而且会优先于构造函数执行

构代码块和构造函数的区别:

  • 构造代码块:是给所有对象进行统一的初始化。所有对象都会调用这个代码块。只要对象已建立,就会调用这个代码块。
  • 构造函数:是给与之对应的对象进行初始化。具有针对性。

构造代码块的使用:
把不同对象的共性的初始化内容定义在构造代码块中。

4. this

this代表本类对象,代表它所在函数所属的对象。
即:哪个对象在调用this所在的函数,this就代表哪个对象。
应用:当定义类中功能时,该函数的内部要用到该函数所属的对象时,就用this来表示这个对象。但凡本类功能中用到本类对象,这时用this来表示这个对象。

this语句:用于构造函数之间的相互调用,调用格式:this(实际参数);
this语句只能定义在构造函数的第一行,因为初始化的动作必须要先执行。否则编译失败。例如:

class Demo
{
    Demo()
    {
        ...//无参构造函数
    }

    Demo(int n)
    {
        this();//this语句,调用上面定义的无参构造函数
    }
}

5. 静态:static

用法:作为一个修饰符,用于修饰成员(成员变量、成员函数)。不能修饰局部变量
特点:

  1. 想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。
  2. 被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
  3. 静态随着类的加载而加载。而且优先于对象存在。

弊端:

  1. 有些数据是对象特有的数据,是不可以被静态修饰的,因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就会出问题。所以在定义静态时,必须要明确,这个数据是否是被对象所共享的。
  2. 静态方法只能访问静态成员,不可以访问非静态成员。因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
  3. 静态方法中不能使用this、super关键字。因为this代表对象,而静态存在时,可能还没有对象,所有this无法使用。
  4. 生命周期过长。

静态成员的使用
成员分为两种:

  1. 成员变量。(数据共享时静态化)
    该成员变量的数据是否对于所有的对象都一样:
    • 如果是,那么该变量需要被静态修饰,因为是共享数据。
    • 如果不是,那么就是说这是对象的特有数据,要存储到对象中。
  2. 成员函数。(方法中没有调用特有数据时就定义为静态)
    该函数是否访问了对象中的特有数据:
    • 如果有访问特有数据,那么方法不能被静态修饰。
    • 如果没有访问过特有数据,那么这个方法需要被静态修饰。
      主函数是静态的

每个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便复用。虽然可以通过创建类的对象来使用工具方法,对数据进行操作,但是存在以下问题:
1. 对象是用于封装数据的,可是工具类对象并不封装特有数据。
2. 操作数据的每一个方法都没有用到工具类的特有数据。

这时,为了让程序更加严谨,是不需要对象的。可以将工具类中的方法都定义成静态(static),直接用类名调用即可。将方法都静态化后,可以方便于使用,但是该类还是可以被其他程序建立对象,为了更为严谨,应该强制让该类不能建立对象。可以通过将构造函数私有化来完成。

成员变量和静态变量的区别:
1. 成员变量所属于对象,所以也称为实例变量。
静态变量所属于类,所以也称为类变量。
2. 成员变量存在于堆内存中。
静态变量存在于方法区中。
3. 成员变量随着对象创建而存在。随着对象被回收而消失。
静态变量随着类的加载而存在,随着类的消失而消失。
4. 成员变量只能被对象所调用。
静态变量可以被对象调用,也可以被类名调用。

所以,成员变量可以成为对象的特有数据,静态变量可以称为对象的共有数据。

静态代码块
就是一个有静态关键字标示的一个代码块区域。定义在类中。如:

class Demo
{
    static
    {
        ...//静态代码块
    }
    ...
}

作用:可以完成类的初始化。静态代码块随着类的加载而执行,而且只执行一次(无论new多少个对象,都只会执行一次)。如果和主函数在同一个类中,会优先于主函数执行。

静态代码块不可以访问非静态成员(因为没有对象)。
构造代码块可以访问非静态成员(构造代码块用于给对象初始化)。

主函数:

public static void main(String[] args)
{
    ...
}

main函数是程序的入口,被JVM调用。其中各个字段的含义如下:
public:代表函数的访问权限(是最大的)。
static:代表主函数随着类的加载就已经存在了。不需要对象,可直接用类名调用。
void:主函数没有具体的返回值。
main:主函数特定的名称。
(String[] args):主函数的参数是一个字符串数组。

主函数的格式是固定的。
jvm默认传递的长度为0的字符串数组,在运行该类时,也可以指定具体的参数进行传递。可以在控制台运行该类时,在后面加入参数。参数之间通过空格隔开。jvm会自动将这些字符串参数作为args数组中的元素,进行存储。

静态代码块、构造代码块、构造函数同时存在时的执行顺序:
静态代码快->构造代码块->构造函数

匿名对象的使用:
1. 当对象的方法只调用一次时,可以使用匿名对象来完成,这样书写比较简化。例如:

new Demo().run();

如果对象对成员进行多次调用,则不能使用匿名对象,必须给对象起名字。
2. 可以将匿名对象作为函数的实参传入,例如:

show(new Demo());

6. 继承:extends

将几种事物的共性部分提取出来,单独进行描述,封装成一个类,再让这几种事物与这个类有关系即可。
好处:
1. 提高了代码的复用性。
2. 让类与类之间产生了关系,为面向对象的另一个特征:多态提供了前提。

父类的由来:其实是由多个类不断向上抽取共性内容而来的。
注意:千万不能为了获取其他类的功能简化代码而继承。必须是类与类之间有所属关系( … is a …)才可以继承。

Java中对于继承,Java只支持单继承。Java虽然不直接支持多继承,但是保留了这种多继承的机制,进行改良。

单继承:一个类只能有一个父类。
多继承:一个类可以有多个父类。

Java不支持多继承呢?
因为当一个类同时继承两个父类时,如果两个父类中有相同的功能,那么子类对象调用该功能时,运行哪一个呢?因为两个父类的方法中都存在方法体。
但是Java保留了这一机制,并用另一种体现形式来完成表示——多实现。

Java支持多重继承( A继承B B继承C C继承D)
多重继承的出现,就有了继承体系。体系中的顶层父类时通过不断向上抽取而来的。它里面定义的该体系最基本,最共性内容的功能。
所以,想要使用一个体系,直接查阅该系统中的父类的功能即可知道该体系的基本用法。那么想要使用一个体系时,需要建立对象。建议建立最子类的对象,因为最子类的的对象不仅可以使用父类的功能,还可以使用子类自身的特有的一些功能。
简单的说:使用一个继承体系,查阅厅层父类的内容,创建底层子类的对象。

子父类出现后,类成员的特点:
类中成员:成员变量、成员函数、构造方法。
1 . 成员变量
当子、父类中出现了非私有的同名成员变量时:
子类要想访问本类中的变量,通过this调用。
子类想要访问父类的同名变量,通过super调用。

super的使用和this的使用几乎一致:
this:代表是本类类型的对象引用。
super:代表是子类所属的父类中的内存空间引用。

注意:子、父类中通常是不会出现同名成员变量的,因为父类中只要定义了,子类就不用再定义了,直接继承过来使用既可以。

2 . 成员函数
当子、父类中出现了一模一样的方法时,建立子类的对象调用的是子类的方法,好像父类中的方法被覆盖掉了一样。这是函数的另一个特性:覆盖(复写、重写)。
当子类继承父类,沿袭了父类的功能到子类中,但是子类虽然具备了该功能,但是功能的内容却和父类不一致。这时没有必要重新定义新功能,而是使用覆盖技术,保留父类的功能定义,并重写功能内容。

覆盖的注意事项:
类覆盖父类,必须保证子类权限大于等于父类的权限,才可以覆盖,否则编译失败。
静态只能覆盖静态,而不能覆盖非静态。

重载与重写的区别:
重载:只看同名函数的参数列表(不一样才能重载,不看返回值)。
重写:子、父类的方法的参数列表要一模一样。

3 . 构造函数
子类的所有的构造函数的第一行都有一条隐式的语句:

super();//表示父类的构造函数,并会调用父类中的空参数的构造函数。

所以子类的构造函数运行时,都会先运行父类的构造函数。这是由于子类继承父类,会继承到父类的数据,所以必须要先调用父类的构造函数以对继承的数据进行初始化。

子类的实例化过程:
子类的所有的构造函数默认都会访问父类的空参数构造函数,因为子类每一个构造函数内的第一行都有一句隐式 super(); 语句。当父类没有空参数的构造函数时,子类必须通过手动调用super来调用指定要访问的构造函数。当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少有一个构造函数会访问父类的构造函数。

注意:

  • 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();
  • 如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数。
  • 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。
  • super()和this()不可以同时出现的构造函数中。两个语句只能有一个定义在第一行,所以只能出现其中一个。super()或者this()都是调用构造函数,构造函数用于初始化,所以初始化的动作要先完成。所以super()和this()语句都必须在第一行。

7. final

继承的一个弊端:打破了封装性。对于一些类,或者类中功能,是不需要被继承或者复写的。这时就要使用final。

  1. 这个关键字是一个修饰符,可以修饰类,方法,变量。
  2. 被final修饰的类是一个最终类,不可以被继承。避免继承和被子类复写功能。
  3. 被final修饰的方法是一个最终方法,不可以被覆盖。
  4. 被final修饰的变量是一个常量,只能赋值一次。可以修饰成员变量和局部变量。
  5. 内部类定义在类中的局部的位置时,只能访问被final修饰的局部变量。

在描述事物时,出现一些数据,它的值是固定的。为了增强阅读性,给这些变量起一个名字,方便于阅读。而这些值不需要被改变,所以加上final修饰,使得程序更为严谨。如:

public static final double PI = 3.1415926535;

8.抽象类和抽象方法:abstract

当多个相关的类中出现相同的功能,但是功能的主体不同,这时可以进行向上抽取。可以只抽取功能的定义(成员函数的声明),而不抽取功能的主体(成员函数的定义)。所抽取的功能需要被abstract所标示,声明为抽象方法。

抽象方法所在的类一定要标示为抽象类,也就是说该类需要被abstract关键字所修饰。

抽象类的特点:

  1. 抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
  2. 抽象方法只定义方法声明,并不定义方法实现。
  3. 抽象类不可以创建对象(实例化)。
  4. 抽象类中的方法要被调用,必须由子类复写其所有的抽象方法后,建立子类对象来调用。只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。

注意:

  1. 抽象类有构造函数,用于给子类对象进行初始化。
  2. 抽象类中可以定义非抽象方法,抽象类和一般的类没有太大的区别,都是在描述事物。只是抽象类在描述事物时,有些功能没有具体的实现。所以抽象类定义时,和一般类一样,都需要定义属性和行为。只不过比一般类多了一个抽象函数,而且不能用于创建对象。
  3. 抽象类中可以不定义抽象方法,这样做的目的仅仅是不让该类创建对象。

9. 接口:interface

可以认为是一种特殊的抽象类。
当抽象类中的全部方法都是抽象方法时,那么该类可以通过接口的形式表示。用关键字interface定义。接口中所包含的成员,最常见的有全局常量抽象方法

接口中的成员都有固定的修饰符:

  • 成员变量:public static final
  • 成员方法:public abstract

例如:

interface Inter
{
    public static final int num = 10;
    public abstract void show();
}

由于接口中有抽象方法,因此接口不可以实例化。接口的子类必须实现了接口中的所有的抽象方法后,该子类才可以实例化。否则该子类还是一个抽象类。

类与类之间存在着继承关系,类与接口之间存在的是实现关系。继承使用关键字extends,实现使用关键字implements。

接口与类不一样的地方就在于:接口可以被多实现。这就是多继承改良后的结果。Java通过多实现机制来体现多继承。不允许多实现时,多个接口内有同名,同参数列表的函数。

一类在继承另一个类的同时,还可以实现多个接口。所以接口的出现避免了但继承的局限性。还可以将类进行功能的扩展。

其实Java中是有多继承的。接口与接口之间存在着继承关系。接口可以多继承接口。

接口都用于设计上,特点有:

  1. 接口是对外提供的规则。
  2. 接口是功能的扩展。
  3. 接口的出现降低了耦合性。

抽象类与接口:
抽象类:一般用于描述一个体系单元,将一组共性内容进行抽取。可以在类中定义抽象内容让子类实现。可以定义非抽象内容让子类直接使用。它里面定义的都是一些体系中的基本内容。
接口:一般用于定义对象的扩展功能,是在继承之外还需这个对象具备的一些功能。

抽象类和接口的共性:都是不断向上抽取的结果。

抽象类和接口的区别:

  1. 抽象类只能被继承,而且只能被但继承。接口需要被实现,而且可以多实现。
  2. 抽象类中可以定义非抽象方法,子类可以直接继承使用。接口中都是抽象方法,需要子类去实现。
  3. 抽象类使用的是“is a” 关系。接口使用“like a”关系。
  4. 抽象类的成员修饰符可以自定义。接口的成员修饰符是固定的,都要被public修饰。

10. 多态

可以理解为事物存在多种形态。函数本身就具备多态性,某一事物有不同的具体体现。

多态的体现:
父类的引用或者接口的引用指向了自己的子类对象。父类的引用也可以接收自己的子类对象。

多态的前提:

  1. 必须是类与类之间有关系,比如继承、实现。
  2. 通常会有覆盖操作。

多态的好处:
提高了程序的扩展性。

多态的弊端:
只能使用父类的引用访问父类的成员,如果想要调用子类的特有方法,则需要将父类的引用强制类型转换成子类类型(向下转型),前提是父类的引用实际指向子类的对象。要判断对象具体属于哪个子类类型,则需要使用关键字instanceof,格式为:<对象 instanceof 类型>,判断一个对象是否所属于指定的类型。

注意:不能将父类对象转换成子类类型,能进行转换必须是父类的引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。多态自始至终都是子类对象在做变化。

多态出现以前是创建对象并指挥对象做事情。出现多态以后,可以找到对象的共性类型,直接操作共性类型做事情即可,这样可以指挥一批对象做事情,通过操作父类或者接口来实现。

多态在子、父类中成员上体现的特点:

  1. 成员变量:
    在编译时期:参考的是引用变量类型所属的类中是否有调用的成员。(编译时不产生对象,只检查语法错误)。
    运行时期:也是参考引用变量类型所属的类中是否有调用的成员。
    无论编译和运行,成员变量参考的都是引用变量所属的类中的成员变量。
    成员变量 – 编译、运行 = 左边

  2. 成员函数:
    编译时期:参考引用型变量所属的类中是否有调用的方法。
    运行时期:参考的是对象所属的类中是否有调用的方法。
    这是因为在子、父类中,对于一模一样的成员函数,有一个特性:覆盖
    成员函数,编译看引用型变量所属的类,运行看对象所属的类。
    成员函数 – 编译 = 左边, 运行 = 右边

  3. 静态函数:
    编译时期:参考的是引用型变量所属的类中是否有调用的成员。
    运行时期:也是参考引用型变量所属的类中是否有所调用的成员。
    因为静态方法不从属于对象,而从属于方法所在的类。调用静态方法的引用是哪个类的引用就调用哪个类的静态方法。
    静态函数–编译、运行 = 左边

静态绑定:静态成员(变量、函数)绑定于类名。
动态绑定:非静态成员绑定于对象(this、super)。

11.Object

Object为多有类的直接或者间接的父类,Java认为所有的对象都具备一些基本的共性内容,这些内容可以不断的向上抽取,最终就抽取到了一个最顶层的类Object中,该类中定义的就是所有对象都具备的功能。

Object类中的方法:
1 . boolean equals(Object obj):用于比较两个对象是否相等,其实内部比较的就是相隔对象的地址。而根据对象的属性不同,判断对象是否相同的具体内容也不一样。所以定义类时,一般都要复写equals方法,建立本类特有的判断对象是否相同的依据。例如:

public boolean equals(Object obj)
{
    if(!(obj instanceof Person))//判断obj是否指向的对象为Person类的对象
    {
        return false;
    }

    Person p = (Person)obj;//强制类型转换
    return this.age == p.age;//根据age来判断是否相同
}

2 . String toString():将对象变成字符串,默认返回的格式为:类名@哈希值 ,等价于

getClass().getName() + '@' + Integer.toHexString(hashCode())

为了让对象对应的字符串有意义,可以通过复写toString方法建立该类对象自己特有的字符串表现形式。如:

public String toString()
{
    return "person : " + age;
}

3 . Class getClass():获取任意对象运行时所属的字节码文件对象。
4 . int hashCode():返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。

通常 equals、toString、hashCode在应用中都会被复写,建立具体对象的特有的内容。

12.内部类

如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象。这时,为了方便设计和访问,直接将A类定义在B类中。就可以了。A类就称为内部类。
当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容。
内部类的访问规则:
1. 内部类可以直接访问外部类的成员,包括私有
2. 外部类要访问内部类,必须要建立内部类的对象。
例如:

class Outer
{
    private int x = 3;

    class Inner//内部类,注意:内部类可以被private修饰,外部类不可以
    {
        void fun()
        {
            System.out.println("..." + x);//内部类可以直接访问外部类成员
        }
    }

    void method()
    {
        Inner in = new Inner();//外部类必须要先建立内部类的对象,才能访问内部类的成员
        in.fun();
    }
}

class InnerClassDemo
{
    public static void main(String[] args)
    {
        Outer out = new Outer();
        out.method();//访问外部类的成员,间接访问内部类的成员

        Outer.Inner in = new Outer().new Inner();//直接访问内部类的成员
        in.fun();
    }
}

之所以内部类可以直接访问外部类成员,是因为内部类持有一个外部类的引用,格式为 外部类名.this ,如果内部类与外部类有重名的成员,要在内部类访问该成员,则可以通过该引用来访问。内部类可以定义在外部类中的成员位置上,也可以定义在外部类中的局部位置上。当内部类被定义在局部位置上,只能访问局部中被final修饰的局部变量。

访问格式:

1 . 当内部类定义在外部类成员位置上,而且非私有,可以在外部其他类中,直接建立内部类对象。格式: 外部类名.内部类名 变量名 = 外部类对象.内部类对象。例如:

Outer.Inner in = new Outer.new Inner();

2 . 当内部类定义在成员位置上,就可以被成员修饰符所修饰,如private:将内部类在外部类中封装。static:内部具有static的特性。当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。

在外部其他类中,直接访问静态内部类的方法:
非静态成员:

new Outer.Inner().function();

静态成员:

Outer.Inner.function();

注:当内部类中定义了静态成员,该内部类必须被static修饰。当外部类中的静态方法访问内部类时,该内部类也必须是被static修饰的。

3 . 当内部类被定义在局部时(某个方法内),其访问访问的方式不变,但是:

  • 不能被static、private修饰,且内部不能定义static成员。
  • 可以直接访问外部类的成员,因为还持有外部类的引用。
  • 但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

匿名内部类:
没有名字的内部类。就是内部类的简化形式。一般只用一次就可以使用这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部类,前提是该内部类必须继承一个类或者实现接口

匿名内部类的使用场景:
当函数的参数是接口类型的引用时,如果接口中的方法不超过3个。可以用过匿名内部类来完成参数的传递。在创建匿名内部类时,该类中封装的方法不要过多,最好是在两个或者两个以内。

匿名内部类的格式:
new 父类名 | 接口名(可以接参数){ 定义子类成员或者覆盖父类方法 }.方法

new Object()
{ 
    void show()
    {
        System.out.println("show run"); 
    }
}.show();//通过匿名内部类创建一个Object类的子类对象,再调用show方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值