第6章:面向对象编程(下)
1、关键字:static
1.1 引入
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生对象,这时,系统才会分配内存空间给对象,其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据再内存空间里只有一份。
1.2 使用说明:
1.2.1 static概念:静态的,随着类的加载而加载。
1.2.2 static可以用来修饰:属性、方法、代码块、内部类
1.2.3 使用static修饰属性:静态变量(类变量)
(1) 属性:按是否使用static修饰分为静态属性(静态变量)和非静态属性(实例变量/属性)。
实例变量:当我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象的非静态属性时,不会导致其他对象中的同样属性值的修改。
静态变量:当我们创建了类的多个对象,每个对象都共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
(2) static修饰属性的其他说明
a、静态变量随着类的加载而加载,可以通过“类.静态变量”的方式直接调用静态变量。
b、静态变量的加载要早于对象的创建。
c、由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
d、调用:
类:可以调用类变量。
对象:可以调用类变量和实例变量。
(3) 类变量和实例变量的内存解析:
栈:存放局部变量
堆:存放new出来的结构:对象、数组
方法区:存放类的加载信息、静态域、常量池
1.2.4 使用static修饰方法:静态方法、类方法
(1) 随着类的加载而加载,可以通过“类.静态方法”的方式进行调用。
(2) 调用:
类:可以调用静态方法。
对象:可以调用静态方法和非静态方法。
(3) 静态方法中,只能调用静态的方法或属性(即不能使用this,this表示当前对象,而静态还没有创建对象);非静态方法中,既可以调用非静态方法或属性,也可以调用静态的方法或属性。
1.2.5 static注意点:
在静态的方法内,不能使用this关键字、super关键字。
对于静态结构前没有声明的,都是通过类去调用,即类.静态结构(eg:类名.静态方法或类名.静态属性)
关于静态属性和静态方法的使用,大家都从生命周期的角度去理解,即最开始是创建类,然后再有对象,然后是对象的消亡,最后是类的消亡。
1.2.6 开发中,如何确定一个属性、方法是否要声明为static的?
属性: 属性可以被多个对象所共享的,不会随着对象的不同而不同的属性声明为static。
方法:操作静态属性的方法,通常设置为static;工具类中的方法,习惯上声明为static(没有必要造一个对象,再去调用该方法)。
1.2.7 static的在设计模式(单例模式)上的应用
设计模式:实在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索。即套路。
设计模式分类:设计模式可以分为23种:创建型模式(5种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;结构性模式(7种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式;行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
单例(Singleton)设计模式: 采用一定的方法保证在整个软件系统中,对某个类中能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。如果我么要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类的内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义为静态的。
单例模式的优点:
单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
单例模式的实现:
1、饿汉式单例模式
package Singleton;
/*
* 单例设计模式(饿汉式)
*/
public class SingletonTest1 {
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
}
}
//银行类为单例,即只创建一个对象
class Bank{
//1、私有化类的构造器 (不让其在类外部创建类的对象)
private Bank(){
}
//2、内部创建类的对象(即通过类中的属性去获取该类的对象)
//4、要求此对象也必须是静态的:由于我们第三步需要返回该类的对象,又因为第三步中的方法是静态的,所以该属性也要是静态的
private static Bank instance = new Bank();
//3、提供公共的静态方法,调用类的对象
//由于在该类的外部无法创建该类的对象,那么我们需要将该方法设置为static
//这样我们就可以直接通过类去调用该方法,而不用去创建其对象
public static Bank getInstance(){
return instance;
}
}
2、懒汉式单例模式
package Singleton;
/*
* 单例设计模式(懒汉式)
*/
public class SingletonTest2 {
Order order1 = Order.getInstance();
}
class Order{
//1、私有化类的构造器
private Order(){
}
//2、声明当前类对象
//4、此对象也必须声明为static
private static Order instance = null;
//3、 声明public、static的返回当前类对象的方法
public static Order getInstance(){
if(instance == null)instance = new Order();
return instance;
}
}
饿汉式VS懒汉式:
区分:懒汉式:什么时候要用就什么时候创建对象;饿汉式:在类创建的时候就创建了该类。
饿汉式:
(1)对象的加载时间过长。(弊)
(2) 饿汉式是线程安全的。(利)
懒汉式:
(1)延迟对象的创建。(利)
(2)懒汉式是线程不安全的。(弊)
2、理解main方法的语法
2.1 main方法的使用说明:
-
main()方法作为程序的入口
-
main()方法也是一个普通的静态方法
-
main()方法可以作为我们与控制台交互的方式,在控制台中运行字节码文件的时候,直接在后面空格输入要输入的内容给字符串数组args(如:java 字节码名 输入的内容)
3、类的成员之四:代码块(初始化块)
3.1 作用: 用来初始化类、对象
3.2 结构: 一对花括号,如果有修饰,只能使用static进行修饰。
根据是否有static修饰,可以将代码块分为静态代码块和非静态代码块。
静态(static)代码块:
内部可以有输出语句。
随着类的加载而执行,只执行一次(即类加载的那一次,只要类不重新加载,就不会执行)
作用:在加载类时,可以初始化类的信息。
如果一个类中定义了多个静态代码块,我们按照其声明的先后顺序执行。并且静态代码块的执行要优先于非静态代码块(因为是现有类的加载,才有对象的创建)
静态代码块中,只能调用静态的结构(属性或方法),因为随着类的加载,只有静态的结构被加载了。
非静态代码块:
内部可以有输出语句。
随着对象的创建而执行,没创建一个对象,就执行一次非静态代码块。
作用:可以在创建对象时,对对象的属性等进行初始化。
如果一个类中定义了多个非静态代码块,我们按照其声明的先后顺序执行。并且都晚于静态代码块的执行。
非静态代码块中可以调用静态结构和非静态结构。
3.3 对属性赋值先后顺序的总结:
- 默认初始化
- 显示初始化 / 在代码块中赋值(两者先后看写的顺序)
- 构造器中初始化
- 创建对象后,通过“对象.属性”或“对象.方法”的方式进行赋值。
注:对于有继承关系的类,都是从父类开始,往子类进行加载的,因此静态代码块的调用时从父类到子类的;在创建其子类对象的时候,也是从父类开始向子类进行创建的(因为有父类,才能够再子类中取调用父类的构造器)。因此非静态的代码块也是从父类到子类进行调用的,并且,非静态代码块的调用要先于构造器。
package Block;
import org.omg.Messaging.SyncScopeHelper;
public class OrderTest {
public static void main(String[] args) {
new tail();
}
}
class head{
static {
System.out.println("head的静态代码块");
}
{
System.out.println("head的非静态代码块");
}
//构造器
public head(){
super();
System.out.println("head的构造器");
}
}
class mid extends head{
static{
System.out.println("mid的静态代码块");
}
{
System.out.println("mid的非静态代码块");
}
//构造器
public mid(){
super();
System.out.println("mid的构造器");
}
}
class tail extends mid{
static{
System.out.println("tail的静态代码块");
}
{
System.out.println("tail的非静态代码块");
}
//构造器
public tail(){
super();
System.out.println("tail的构造器");
}
}
//运行结果:
//head的静态代码块
//mid的静态代码块
//tail的静态代码块
//head的非静态代码块
//head的构造器
//mid的非静态代码块
//mid的构造器
//tail的非静态代码块
//tail的构造器
//总结:由父及子,静态先行。
4、关键字:final
4.1 final:最终的
4.2 修饰对象:类、方法、变量
-
final修饰类:此类不能被其他类所继承。如:String类、System类、StringBuffer类
-
final修饰方法:表明此方法不可以被重写。比如getclass方法(获取对象所属的类)。
-
final修饰变量:此时的“变量”就称为是一个常量。final修饰属性,可以考虑的赋值的位置有:显示初始化、代码块中初始化、构造器初始化;final修饰局部变量,尤其是使用final来修饰形参时,表明此形参时一个常量。当我们调用此方法时,给常量形参赋一个实参,一旦赋值以后,就只能在方法体内使用次形参,但不能进行重新赋值。
4.3 static fianl修饰符:可以用来修饰属性和方法。
属性:全局常量。(static表明其是全局,final表明其是常量)
5、抽象类和抽象方法
5.1 抽象类的引入:
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。(即将父类抽象,将子类具体,我们创建对象,通过子类去创建) 一般,我们通过abstract关键词来修饰抽象类。
5.2 abstract关键字的使用:
5.2.1 翻译:抽象的
5.2.2 修饰的结构:类、方法
5.2.3 abstract 修饰类: 抽象类
- 此类不能实例化。
- 抽象类中仍然提供构造器。(虽然自己不能去实例化,但子类还是要进行实例化的,便于子类实例化时候的调用,涉及子类对象实例化的全过程)
- 开发中都会提供抽象类的子类,让子类对象实例化,完成相关的操作。
5.2.4 abstract修饰方法:抽象方法
- 抽象方法只有方法的声明,没有方法体。
- 包含抽象方法的类一定是一个抽象类(如果不是抽象类,那么类可以实例化,那么可以取调这个抽象方法,但抽象方法不应该被调用)。反之,抽象类中可以没有抽象方法的。
- 若子类重写了父类中的所有的抽象方法后,此子类方可实例化;若子类没有重写父类中的所有抽象方法,则意味着次子类也是一个抽象类,需要使用abstract去修饰一下。
5.2.4 abstract使用上的注意点:
- abstract不能用来修饰属性、构造器等结构。
- abstract不能用来修饰私有方法(私有方法不能被重写,子类无法访问父类的私有方法)、静态方法(static不是重写)、final的方法(不能被重写)、final的类(不能继承,那么该抽象类不能被子类创建实例)。
5.2.5 创建抽象类的匿名子类对象:
package Anonymous_class;
public class Test {
public static void main(String[] args) {
//创建一个非匿名子类
//那么就要先创建一个该抽象类Person的子类,并重写Person中的抽象方法
//然后通过该子类去实例化,即是创建一个非匿名子类
//创建一个匿名子类的对象:p
//利用多态,并在new的同时为子类对象进行重写抽象父类的抽象方法
//优点:不用再去通过建立一个子类,然后将该子类进行实例化。
Person p = new Person(){
@Override
public void breath() {
// TODO Auto-generated method stub
System.out.println("呼吸!");
}
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃东西!");
}
};
Test.show(p);
//show(p);
//创建匿名子类的匿名对象:
Test.show(new Person(){
@Override
public void breath() {
// TODO Auto-generated method stub
System.out.println("呼吸!");
}
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃东西!");
}
});
}
public static void show(Person person){
person.eat();
person.breath();
}
}
abstract class Person{
private String name;
private int age;
public abstract void breath();
public abstract void eat();
}
匿名对象:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。
匿名类:也叫匿名内部类,是内部类的一种匿名类在类中只能使用一次,它通常用来简化代码的编写,但使用匿名类还有一个前提条件:它必须继承一个父类或者一个接口,因此这个匿名类会被默认为这个父类或者接口的子类或实现。不用再去特意新建一个类,然后再通过该类去进行实例化。
5.2.6 抽象类的应用:模板方法设计模式
概念: 抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。
解决问题:
(1)当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
(2)换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。
例子代码:
package TemplateMethod;
/*
* 抽象类的应用:模板方法的设计模式
*
*/
public class TemplateTest {
public static void main(String[] args) {
SubTemplate t = new SubTemplate();
t.spendTime();
}
}
abstract class Template{
//计算某段段码执行所需要花费的时间
public void spendTime(){
long start = System.currentTimeMillis(); //获取1970到现在的时间
code(); //不确定的部分、异变的部分,通过抽象方法进行填充,然后在子类中进行实现
long end = System.currentTimeMillis();
System.out.println("花费的时间为: " + (end - start));
}
public abstract void code();
}
class SubTemplate extends Template{
public void code(){
for(int i = 2; i < 1000; i ++){
boolean isFlag = true;
for(int j = 2; j < Math.sqrt(i); j ++){
if(i % j == 0){
isFlag = false;
break;
}
if(isFlag){
System.out.println(i);
}
}
}
}
}
6、接口(interface)
6.1引出:
-
有时必须从几个类中派生出一个子类,继承他们所有的属性和方法,但Java不支持多重继承。
-
有时必须从几个类中抽取一些共同的行为特征,而他们之间又没有继承的关系,仅仅是具有相同的行为特征而已。比如说手机、Mp3都是通过USB接口。
-
接口就是规范,定义的是一组规则,体现了显示世界中“如果你是/要……则必须能……”的思想。继承是一个是不是的关系,而接口实现则是能不能的关系。
-
接口的本质是契约,标准,规范,就像我们的法律一样,制定好以后大家都要遵循。
举例:
虚线是接口,实现是继承。
6.2 接口的使用:
1、接口使用interface来定义(语法格式 interface 名称{})
2、Java中,接口和类是并列的结构
3、定义接口:定义接口中的成员
3.1、JDK7:以前,只能定义全局常量(public static final的,书写可以省略)和抽象方法(public abstract的,书写可以省略)。
3.2、JDK8:除了定义全局常量和抽象方法以外,还可以定义静态方法、默认方法(略)
public interface CompareA {
//静态方法
public static void method1(){
System.out.println("comparaA:北京");
}
//默认方法
public default void method2(){
System.out.println("comparaA:上海");
}
default void method3(){
System.out.println("comparaA:上海");
}
}
public interface CompareB {
default void method3(){
System.out.println("comparaB:上海");
}
}
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
//知识点1:接口中定义的静态方法,只能通过接口来调用
CompareA.method1();
//知识点2:通过实现类的对象,可以调用接口中的默认方法
//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写的方法
s.method2();
//知识点3:如果实现类[对接口](或子类[对父类])继承的父类和实现的接口中声明了同名同参数的方法
//那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数方法——类优先原则(接口稍后原则)
//对于属性,则没有先后,会出现编译错误
//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法method3
//那么在实现类没有重写此方法的情况下,会报错。-- 接口冲突
//这就需要我们必须在实现类中重写此方法!
s.method3();
s.mymethod();
}
}
class SubClass extends SuperClass implements CompareA,CompareB{
//重写接口默认方法
public void method2(){
System.out.println("SubClass:上海 ");
}
//知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
public void mymethod(){
this.method2(); //调用自己定义的重写方法
super.method3();//调用父类中声明的
//调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}
}
public class SuperClass {
public void method3(){
System.out.println("superclass:北京");
}
}
4、接口中不能定义构造器。即接口无法实例化。
5、Java开发中,接口通过让类去实现的方式(implements)来使用。如果实现类覆盖了接口中的所有抽象方法,则次实现类就可以实例化;如果实现类没有覆盖接口中的所有的抽象方法,则此实现类仍为一个抽象类。
6、Java中的类可以实现多个接口,弥补了Java单继承性的局限性。
7、对于一个类,先继承父类,后写需要实现的接口。格式:class A extends BB implements CC,DD,EE{};
8、接口与接口之间可以继承,而且可以多继承。interface CC extends AA,BB{};
特点:
1、接口的具体使用能够体现多态性,通过其子类去进行实例化。
2、接口,实际上可以看做是一种规范。对于项目的具体需求是多变的,我们必须以不变应万变才能从容开发,此处的不变就是规范,因此我们开发项目往往都是面向接口编程(接口的主要用途就是被实现类实现)
3、开发中,体会面向接口编程。
6.3 接口匿名实现类对象:
package Anonymous_Interface;
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
//1.创建了接口的非匿名实现类的非匿名对象flash
Flash flash = new Flash();
com.transferData(flash);
System.out.println("****************************");
//2.创建了接口的非匿名实现类的匿名对象
com.transferData(new Printer());
System.out.println("****************************");
//3.创建了接口的匿名实现类的非匿名对象
//匿名实现类即不适用其可以实例化的子类进行实例化
//直接通过子类进行实例化
USB phone = new USB(){
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("U盘开始工作!");
}
@Override
public void end() {
// TODO Auto-generated method stub
System.out.println("U盘结束工作!");
}
};
com.transferData(phone);
System.out.println("****************************");
//4.创建了接口的匿名实现类的匿名对象
com.transferData(new USB(){
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("U盘开始工作!");
}
@Override
public void end() {
// TODO Auto-generated method stub
System.out.println("U盘结束工作!");
}
});
}
}
class Computer{
public void transferData(USB usb){
usb.start();
System.out.println("具体传输数据的细节");
usb.end();
}
}
class Flash implements USB{
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("U盘开始工作!");
}
@Override
public void end() {
// TODO Auto-generated method stub
System.out.println("U盘结束工作!");
}
}
class Printer implements USB{
@Override
public void start() {
// TODO Auto-generated method stub
System.out.println("打印机开始工作!");
}
@Override
public void end() {
// TODO Auto-generated method stub
System.out.println("打印机结束工作!");
}
}
//定义接口
interface USB{
public abstract void start();
public abstract void end();
}
6.4 接口的应用:代理模式(Proxy)
概述: 代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
具体例子代码:
package Proxy;
/*
* 接口的应用:代理模式
*/
public class NetWorkTest {
public static void main(String[] args) {
//不直接通过server被代理类去调用
//通过代理类去调用方法的同时去调用server中的方法
Server server = new Server();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse();
}
}
interface NetWork{
public void browse();
}
//被代理类
class Server implements NetWork{
@Override
public void browse() {
// TODO Auto-generated method stub
System.out.println("真实的服务器访问网络");
}
}
//代理类
class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work){
this.work = work;
}
public void check(){
System.out.println("联网之前的检查工作!");
}
@Override
public void browse() {
// TODO Auto-generated method stub
check();
work.browse();
}
}
/*
* 应用场景:
* 1.安全代理:屏蔽对真实角色的直接访问,通过代理去访问。
* 2.远程代理:通过代理类处理远程方法调用(RMI)
* 3.延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。
* 4.静态代理:(静态定理代理类)
* 5.动态代理:(动态生成代理类)
6.4 接口的应用:工厂设计模式
概述: 实现了创建者(new对象的)与调用者(拿这个对象去做事)的分离,即将创建对象的具体工厂屏蔽隔离起来,达到提高灵活性的目的。
分类:
无工厂模式:
简单工厂模式:用来生产同一等级结构中的任意产品(对于增加新的产品需要修改已有代码)
工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品)
抽象工厂模式:用来生产不同产品族的全部产品(对于增加新的产品,无能为力;支持增加产品族)
6.5 接口面试题:
1.排错:
interface A {
int x = 0;
}
class B {
int x = 1;
}
class C extends B implements A {
public void pX() {
System.out.println(x); //错误,编译不通过,接口和父类中变量x同名
}
public static void main(String[] args) {
new C().pX();
}
}
/*
接口的实现和类的继承是并列的,因此,对于同名变量x编译器无法区分。对于继承中存在的同名变量,我们使用就近原则(即取直接父类的同名变量值,而不是间接父类的同名变量值)
获取继承类B的x:super.x
获取接口A的x:A.x (因为其是全局常量)
*/
2.排错:
interface Playable {
void play();
}
interface Bounceable {
void play();
}
interface Rollable extends Playable, Bounceable {
Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name = name;
}
public void play() {
ball = new Ball("Football"); //接口中是final,不能进行修改
System.out.println(ball.getName());
}
}
6.6 Java8中关于接口的改进:
7、类的成员之五:内部类
7.1 引入:
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。
7.2 概念:
在java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B为外部类。
7.3 内部类分类: 成员内部类(静态、非静态) 和 局部内部类(方法内、代码块内、构造器内)
class Person{
//静态成员内部类:
static class AA1{
}
//非静态成员内部类
class AA2{
}
//方法中的局部内部类1
public void method(){
//局部内部类
class BB1{
}
}
//代码块中局部内部类2
{
//局部内部类
class BB2{
}
}
//构造器中局部内部类3
public Person(){
//局部内部类
class BB3{
}
}
}
成员内部类特点:
作为外部类的成员(内部类):
-
调用外部类的结构。(外部类.this.结构)
-
可以用static修饰
-
作为类的成员可以被4种不同权限修饰,不同于类,只有缺省和public两种修饰。
作为一个类:
- 类内可以定义属性、方法、构造器等
- 可以被final修饰,表示此类不能被继承,反之,可以继承。
- 可以被abstract修饰,表示该类不能被实例化。
7.4 如何实例化成员内部类的对象:
静态内部类的实例化(不需要外部类的实例化):
外部类.内部类 名称 = new 外部类.内部类();
非静态内部类的实例化:
外部类 p = new 外部类();
p.内部类 名称 = p.new 内部类();
7.5如何在成员内部类中区分调用外部类的结构:
对于同名变量,外部类的成员变量,内部类的成员变量,和方法内的变量。
我们如何在方法内,区分上述三个同名变量。
外部类的成员变量:变量名
内部类的成员变量:this.变量名
方法内的变量:外部类.this.变量名
7.6 开发中局部内部类的使用:
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
//方法一:
class MyComoparable implements Comparable{
@Override
public int compareTo(Object o){
return 0;
}
}
return new MyComparable();
//方法二:匿名类
return new Comparable(){
@Override
public int compareTo(Object o){
return 0;
}
}
}
标签:静态,子类,void,对象,static,面向对象编程,public
From: https://www.cnblogs.com/bananayjy/p/17096684.html