黑马程序员--Java面向对象_黑马java面向对象-程序员宅基地

技术标签: java  黑马程序员  

——- android培训java培训、期待与您交流! ———-

概述

面向对象是基于面向过程的编程思想。

面向过程:强调的是每一个功能的步骤
面向对象:强调的是对象,然后由对象去调用功能

特点
A:是一种更符合我们思想习惯的思想
B:可以将复杂的事情简单化
C:将我们从执行者变成了指挥者

特征

封装性

封装有两个含义。
一是把对象的属性和行为堪称一个密不可分的整体,将两者封装在一个不可分割的独立单位中(对象)。

二是指“信息隐藏”,把不需要让外界知道的信息隐藏起来,有些对象的属性和行为外界可以知道和使用,但不允许修改,另一些属性或行为,不允许外界知道,只允许使用对象的功能。

继承性

继承是提高软件开发效率的重要手段。

继承是首先拥有反映事物一般特性的类,然后在这个基础上派生出反映特殊事物的类。

例如已有普通汽车的类,该类中描述了汽车的普通属性和行为,如四个轮子,发动机,方向盘等等,
可以在这个基础上生产跑车的类,跑车是继承于汽车,跑车不但有用汽车的全部属性和行为,还增加跑车自己特有的属性和行为。

面向对象程序设计中的继承机制大大增加了程序代码的可复用性,提高软件开发效率,降低程序产生错误的可能性,也为程序的修改扩充提供便利。

多态性

多态是面向对象程序设计的有一个重要特征,多态允许程序中出现重名现象。java语言中含有方法重载和对象多态两种形式的多态。

方法重载:在一个类中,允许多个方法使用同一个名字,但方法的参数不同,完成的功能也不同。

对象多态:子类对象可以与父类对象进行相互转换,而且根据其使用的子类不同,完成的功能也不同。

多态的特性使程序的抽象程度和简捷程度更高,有助于程序设计人员对程序的富足协同开发。

面向对象就是一种常见的思想,符合人们的思考习惯。
面向对象的出现,让复杂的问题简单化。
面向对象的出现,让曾经在过程中的执行者,变成了对象中的指挥者。

类与对象

类与对象是Java中最基本,但也是最重要的组成部分。

其实类与现实中的事物有着相似的地方
成员变量 – 事物属性
成员方法 – 事物行为

类:是一组相关的属性和行为的集合。是一个抽象的概念。
对象:是该类事物的具体存在,是一个具体的实例。

例如:学生是一个群体而不是指具体的某个人。我们就可以把学生看成一个类。
三年二班的周杰伦是一个具体的人,那么他就是一个具体的对象,不过他显然也属于学生这个群体。
每个学生都有名字和年龄,这两个属性我们就可以看成是一个类的成员变量。但是每个学生的名字和年龄都是一样的吗?显然不是,这时候对象就派上用场了,我们想得到周杰伦这个对象,那就直接new一个对象,然后分别给名字和年龄这两个属性赋上具体的数据,最后我们就得到了周杰伦的具体对象。
每个学生都要吃饭睡觉上厕所,这三个动作就是类的成员方法,所有的学生都要吃饭睡觉上厕所,周杰伦呢?当然也得要。。所以我们就知道了原来类里面有什么方法,那么它的对象就必须要有什么方法。

class Student {
    //定义变量
    //姓名
    String name;
    //年龄
    int age;
    //地址
    String address;

    //定义方法
    //学习的方法
    public void study() {
        System.out.println("学生爱学习");
    }

    //吃饭的方法
    public void eat() {
        System.out.println("学习饿了,要吃饭");
    }

    //睡觉的方法
    public void sleep() {
        System.out.println("学习累了,要睡觉");
    }
}

测试类

class StudentDemo {
    public static void main(String[] args) {
        //类名 对象名 = new 类名();
        Student s = new Student();

        System.out.println(s.name+"---"+s.age+"---"+s.address);


        //给成员变量赋值
        s.name = "李延旭";
        s.age = 21;
        s.address = "北京";
        //赋值后的输出
        System.out.println(s.name+"---"+s.age+"---"+s.address);

        //调用方法
        s.study();
        s.eat();
        s.sleep();
    }
}

成员变量和局部变量的区别:
1.在类中的位置不同
成员变量定义在类中,整个类中都可以访问。
局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。

2.再内存中的位置不同
成员变量存在于堆内存的对象中
局部变量存在于栈内存的方法中

3.生命周期不同
成员变量随着对象的创建而存在,随着对象的消失而消失。
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。

4.初始化值不同
成员变量都有默认初始化值
局部变量没有默认初始化值

成员方法:定义格式和以前一样,就是去掉了static。

类作为形式参数
如果你看到一个方法需要的参数是一个类名,就应该知道这里实际需要的是一个具体的对象

/*
    形式参数的问题:
        基本类型:形式参数的改变不影响实际参数
        引用类型:形式参数的改变直接影响实际参数
*/
//形式参数是基本类型
class Demo {
    public int sum(int a,int b) {
        return a + b;
    }
}

//形式参数是引用类型
class Student {
    public void show() {
        System.out.println("我爱学习");
    }
}

class StudentDemo {
    //如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
    public void method(Student s) { //调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();
        s.show();
    }
}

class ArgsTest {
    public static void main(String[] args) {
        //形式参数是基本类型的调用
        Demo d = new Demo();
        int result = d.sum(10,20);
        System.out.println("result:"+result);
        System.out.println("--------------");

        //形式参数是引用类型的调用
        //需求:我要调用StudentDemo类中的method()方法
        StudentDemo sd = new StudentDemo();
        //创建学生对象
        Student s = new Student();
        sd.method(s); //把s的地址给到了这里
    }
}

匿名对象

就是没有名字的对象。

匿名对象的应用场景:
A:调用方法,仅仅只调用一次的时候。
注意:调用多次的时候,不适合。
那么,这种匿名调用有什么好处吗?
有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。

B:匿名对象可以作为实际参数传递

class Student {
    public void show() {
        System.out.println("我爱学习");
    }
}

class StudentDemo {
    public void method(Student s) {
        s.show();
    }
}

class NoNameDemo {
    public static void main(String[] args) {
        //带名字的调用
        Student s = new Student();
        s.show();
        s.show();
        System.out.println("--------------");

        //匿名对象
        //new Student();
        //匿名对象调用方法
        new Student().show();
        new Student().show(); //这里其实是重新创建了一个新的对象
        System.out.println("--------------");


        //匿名对象作为实际参数传递
        StudentDemo sd = new StudentDemo();
        //Student ss = new Student();
        //sd.method(ss); //这里的s是一个实际参数
        //匿名对象
        sd.method(new Student());

        //在来一个
        new StudentDemo().method(new Student());
    }
}

封装

隐藏实现细节,提供公共的访问方式

好处:
A:隐藏实现细节,提供公共的访问方式
B:提高代码的复用性
C:提高代码的安全性

private

是一个权限修饰符,私有的意义,可以修饰成员变量和成员方法
被其修饰的成员只能在本类中被访问

private的应用:
把所有的成员变量给private了
提供对应的getXxx()/setXxx()方法

class Demo {
    //int num = 10;
    //用private修饰
    private int num = 10;

    public void show() {
        System.out.println(num);
    }

    private void method() {
        System.out.println("method");
    }

    public void function() {
        method();
    }
}

class PrivateDemo {
    public static void main(String[] args) {
        Demo d = new Demo();
        //不能使用方法私有的成员变量
        //System.out.println(d.num);
        d.show();
        //不能访问私有的成员方法
        //d.method();
        d.function();
    }
}
//定义学生类
class Student {
    //姓名
    private String name;
    //年龄
    private int age;

    //姓名获取值
    public String getName() 
    {
        return name;
    }
    //姓名设置值
    public void setName(String n)
    {
        name = n;
    }
    //年龄获取值
    public int getAge()
    {
        return age;
    }
    //年龄赋值
    public void setAge(int a) 
    {
        age = a;
    }
}

//测试类
class StudentTest 
{
    public static void main(String[] args) 
    {
        //创建学生对象
        Student s = new Student();

        //使用成员变量
        System.out.println(s.getName()+"---"+s.getAge());

        //给成员变量赋值
        //通过方法给赋值
        s.setName("李延旭");
        s.setAge(21);
        System.out.println(s.getName()+"---"+s.getAge());
    }
}

this

当前类的对象引用。简单的记,它就代表当前类的一个对象。
注意:谁调用这个方法,在该方法内部的this就代表谁。

this的应用场景:
解决局部变量隐藏成员变量

class Student {
    //姓名
    private String name;
    //年龄
    private int age;

    //姓名获取值
    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;
    }
}
  • 构造方法

给对象的数据进行初始化

格式:
A:方法名与类名相同
B:没有返回值类型,连void都没有
C:没有具体的返回值

class Student {
    private String name; //null
    private int age; //0

    public Student() {
        System.out.println("这是构造方法");
    }
}

class ConstructDemo {
    public static void main(String[] args) {
        //创建对象
        Student s = new Student();
        System.out.println(s); 
    }
}

构造方法的注意事项:
A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。
注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法

给成员变量赋值有两种方式:
A:setXxx()
B:构造方法

static

针对多个对象有共同的这样的成员变量值的时候,Java就提高了一个关键字来修饰:static。
static的特点:(它可以修饰成员变量,还可以修饰成员方法)
A:随着类的加载而加载,回想main方法。
B:优先于对象存在
C:被类的所有对象共享

什么时候使用静态?
如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
举例:
饮水机(用静态修饰)
水杯(不能用静态修饰)
D:可以通过类名调用
其实它本身也可以通过对象名调用。推荐使用类名调用。

static关键字注意事项
A:在静态方法中是没有this关键字的
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
B:静态方法只能访问静态的成员变量和静态的成员方法

静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法

非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。

简单记:静态只能访问静态。

main方法的格式讲解

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

public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。

static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。

void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。

main:是一个常见的方法入口。我见过的语言都是以main作为入口。

String[] args:这是一个字符串数组。值去哪里了?
这个东西到底有什么用啊?怎么给值啊?
这个东西早期是为了接收键盘录入的数据的。
格式是:
java MainDemo hello world java

代码块

在Java中,使用{}括起来的代码被称为代码块

根据其位置和声明的不同,可以分为
局部代码块:局部位置,用于限定变量的生命周期。

构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。
作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。

静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。
作用:一般是对类进行初始化。

静态代码块,构造代码块,构造方法的执行顺序?
静态代码块 – 构造代码块 – 构造方法

静态代码块:只执行一次
构造代码块:每次调用构造方法都执行

继承

把多个类中相同的内容给提取出来定义到一个类中。
格式:
class 子类名 extends 父类名 {}

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

    public void sleep() {
        System.out.println("睡觉");
    }
}

class Student extends Person {
    }

class Teacher extends Person {
    }

class ExtendsDemo {
    
    public static void main(String[] args) {
        Student s = new Student();
        s.eat();
        s.sleep();
        System.out.println("-------------");

        Teacher t = new Teacher();
        t.eat();
        t.sleep();
    }
}

继承的好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类之间产生了关系,是多态的前提
继承的弊端:
A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。
原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
B:打破了封装性

Java中继承的特点:

  • A:Java只支持单继承,不支持多继承。有些语言是支持多继承,格式:extends 类1,类2,…
  • B:Java支持多层继承(继承体系)

继承的注意事项:

  • A:子类只能继承父类所有非私有的成员(成员方法和成员变量)
  • B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
  • C:不要为了部分功能而去继承

什么时候考虑使用继承
如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
继承其实体现的是一种关系:”is a”。

继承中成员变量的关系:

  • A:子类中的成员变量和父类中的成员变量名称不一样
  • B:子类中的成员变量和父类中的成员变量名称一样

在子类方法中访问一个变量的查找顺序:
- a:在子类方法的局部范围找,有就使用
- b:在子类的成员范围找,有就使
- c:在父类的成员范围找,有就使用
- d:如果还找不到,就报错。

this和super的区别
this代表本类对应的引用。
super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)

用法
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量

B:调用构造方法
this(…) 调用本类的构造方法
super(…) 调用父类的构造方法

C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法

子父类中,成员的特点体现:
1.成员变量
当本类的成员和局部变量同名用this区分
当子父类中的成员变量同名时用super区分父类
this和super的用法很相似
this:代表一个本类对象的引用
super:代表一个父类空间

2成员函数
当子父类中出现成员函数一模一样的情况,会运行子类的函数
这种现象,称为覆盖操作,这是函数在子父类中的特征
函数两个特性:
重载,同一个类中
覆盖,子类中。覆盖也称为重写,覆写。

覆盖的注意事项:
1.子类方法覆盖父类方法时,子类全选必须权限大于等于父类
2.静态只能覆盖静态,或被静态覆盖
3.构造函数
在子类构造对象时,发现,访问子类构造函数时,父类也运行了。
原因是:在子类的构造函数中第一行有一个默认的隐式语句,super()
super()调用的就是父类中的空参构造函数。

class Fu {
    
    Fu() {
        System.out.println("Fu run");
    }

    Fu(int num) {
        System.out.println("Fu:" + num);
    }
}

class Zi extends Fu {
    
    Zi() {
        // super();隐式语句,调用的就是父类中的空参构造函数
        System.out.println("Zi run");
    }

    Zi(int num) {
        // super();这里也有隐式语句super()
        // 用super明确调用父类中的那个构造方法
        super(num);
        this();
        // this和super只能有一个在第一行,this调用了本类中空参构造方法,空参构造方法中也会有一个隐式super()语句。
        // 所以子类中要保证会有一个构造方法访问到父类的构造方法
        System.out.println("Zi:" + num);
    }
}

class ExtendsDemo {
    
    public static void main(String[] args) {
        new Zi();
        new Zi(5);
    }
}

final

可以修饰类,方法,变量
特点:
final可以修饰类,该类不能被继承。
final可以修饰方法,该方法不能被重写。(覆盖,复写)
final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。

常量:
A:字面值常量
“hello”,10,true
B:自定义常量
final int x = 10;

class Fu {
    
    public int num = 10;
    public final int num2 = 20;
}

class Zi extends Fu {
    
    // Zi中的show()无法覆盖Fu中的show()
    public void show() {
        num = 100;
        System.out.println(num);

        //无法为最终变量num2分配值
        //num2 = 200;
        System.out.println(num2);
    }
}

class FinalDemo {
    
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}

final修饰变量的初始化时机
A:被final修饰的变量只能赋值一次。
B:在构造方法完毕前。(非静态的常量)

多态

同一个对象在不同时刻体现出来的不同状态。
多态的前提:
- A:有继承或者实现关系。
- B:有方法重写。
- C:有父类或者父接口引用指向子类对象。

多态的分类
具体类多态

class Fu {
    }
class Zi extends Fu {
    }
Fu f = new Zi();

抽象类多态

abstract class Fu {
    }
class Zi extends Fu {
    }
Fu f = new Zi();

接口多态

interface Fu {
    }
class Zi implements Fu {
    }
Fu f = new Zi();

多态中的成员访问特点
A:成员变量
编译看左边,运行看左边
B:构造方法
子类的构造都会默认访问父类构造
C:成员方法
编译看左边,运行看右边
D:静态方法
编译看左边,运行看左边

为什么?
因为成员方法有重写。

class Fu {
    public int num = 100;

    public void show() {
        System.out.println("show Fu");
    }

    public static void function() {
        System.out.println("function Fu");
    }
}

class Zi extends Fu {
    public int num = 1000;
    public int num2 = 200;

    public void show() {
        System.out.println("show Zi");
    }

    public void method() {
        System.out.println("method zi");
    }

    public static void function() {
        System.out.println("function Zi");
    }
}

class DuoTaiDemo {
    public static void main(String[] args) {
        //要有父类引用指向子类对象。
        //父 f =  new 子();
        Fu f = new Zi();
        System.out.println(f.num);
        //找不到符号
        //System.out.println(f.num2);

        f.show();
        //找不到符号
        //f.method();
        f.function();
    }
}

多态的好处:
- A:提高代码的维护性(继承体现)
- B:提高代码的扩展性(多态体现)

多态的弊端:
父不能使用子的特有功能。
现象:子可以当作父使用,父不能当作子使用。

多态中的转型
- A:向上转型:从子到父
- B:向下转型:从父到子

class Animal {
    
    public void eat(){}
}

class Dog extends Animal {
    
    public void eat() {}

    public void lookDoor() {

    }
}

class Cat extends Animal {
    
    public void eat() {

    }

    public void playGame() {

    }
}

class DuoTaiDemo5 {
    
    public static void main(String[] args) {
        //内存中的是狗
        Animal a = new Dog();
        Dog d = (Dog)a;

        //内存中是猫
        a = new Cat();
        Cat c = (Cat)a;

        //内存中是猫
        Dog dd = (Dog)a; //ClassCastException
    }
}

抽象类

把多个共性的东西提取到一个类中,这是继承的做法。
但是呢,这多个共性的东西,在有些时候,方法声明一样,但是方法体。
也就是说,方法声明一样,但是每个具体的对象在具体实现的时候内容不一样。
所以,我们在定义这些共性的方法的时候,就不能给出具体的方法体。
而一个没有具体的方法体的方法是抽象的方法。
在一个类中如果有抽象方法,该类必须定义为抽象类。

抽象类的特点
A:抽象类和抽象方法必须用关键字abstract修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
C:抽象类不能实例化
D:抽象类的子类
a:是一个抽象类。
b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。

抽象类的成员特点:
A:成员变量
有变量,有常量
B:构造方法
有构造方法
C:成员方法
有抽象,有非抽象

abstract class Fu {
    

    static abstract void show();

    public static void method() {
        System.out.println("method");
    }
}

class Zi extends Fu {
    
    public void show() {}
}

class AbstractDemo3 {
    
    public static void main(String[] args) {
        Fu.method();
    }
}

接口

比如:猫钻火圈,狗跳高等功能,不是动物本身就具备的,
是在后面的培养中训练出来的,这种额外的功能,java提供了接口表示。

接口的特点:
A:接口用关键字interface修饰
interface 接口名 {}
B:类实现接口用implements修饰
class 类名 implements 接口名 {}
C:接口不能实例化
D:接口的实现类
a:是一个抽象类。
b:是一个具体类,这个类必须重写接口中的所有抽象方法。

//定义动物培训接口
interface AnimalTrain {
    
    public abstract void jump();
}

//抽象类实现接口
abstract class Dog implements AnimalTrain {
    
}

//具体类实现接口
class Cat implements AnimalTrain {
    
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}

class InterfaceDemo {
    
    public static void main(String[] args) {
        //AnimalTrain是抽象的; 无法实例化
        //AnimalTrain at = new AnimalTrain();
        //at.jump();

        AnimalTrain at = new Cat();
        at.jump();
    }
}

接口成员特点
成员变量;只能是常量,并且是静态的。
默认修饰符:public static final
建议:自己手动给出。

构造方法:接口没有构造方法。

成员方法:只能是抽象方法。
默认修饰符:public abstract
建议:自己手动给出。

所有的类都默认继承自一个类:Object。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。

类与类:
继承关系,只能单继承,可以多层继承。

类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。

接口与接口:
继承关系,可以单继承,也可以多继承。

interface Father {
    
    public abstract void show();
}

interface Mother {
    
    public abstract void show2();
}

interface Sister extends Father,Mother {
    

}

//class Son implements Father,Mother //多实现
class Son extends Object implements Father,Mother {
    
    public void show() {
        System.out.println("show son");
    }

    public void show2() {
        System.out.println("show2 son");
    }
}

class InterfaceDemo3 {
    
    public static void main(String[] args) {
        //创建对象
        Father f = new Son();
        f.show();

        Mother m = new Son();
        m.show2();
    }
}

抽象类和接口的区别

A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象

接口:
成员变量:只可以常量
成员方法:只可以抽象

B:关系区别
类与类
继承,单继承

类与接口
实现,单实现,多实现

接口与接口
继承,单继承,多继承

设计理念区别
抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

形式参数和返回值

(1)形式参数:
类名:需要该类的对象
抽象类名:需要该类的子类对象
接口名:需要该接口的实现类对象

(2)返回值类型:
类名:返回的是该类的对象
抽象类名:返回的是该类的子类对象
接口名:返回的是该接口的实现类的对象

(3)链式编程
对象.方法1().方法2()…….方法n();

这种用法:其实在方法1()调用完毕后,应该一个对象;
方法2()调用完毕后,应该返回一个对象。
方法n()调用完毕后,可能是对象,也可以不是对象。

内部类

概述:
把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。

内部类的访问特点:
A:内部类可以直接访问外部类的成员,包括私有。
B:外部类要访问内部类的成员,必须创建对象。

内部类位置
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类。

成员内部类:
如何直接访问内部类的成员。
外部类名.内部类名 对象名 = 外部类对象.内部类对象;

成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意:静态内部类访问的外部类数据必须用静态修饰。

class Outer {
    private int num = 10;
    private static int num2 = 100;

    //内部类用静态修饰是因为内部类可以看出是外部类的成员
    public static class Inner {
        public void show() {
            System.out.println(num2);
        }

        public static void show2() {
            System.out.println(num2);
        }       
    }
}

class InnerClassDemo4 {
    public static void main(String[] args) {

        Outer.Inner oi = new Outer.Inner();
        oi.show();
        oi.show2();

        //show2()的另一种调用方式
        Outer.Inner.show2();
    }
}

局部内部类
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

局部内部类访问局部变量的注意事项
A:局部内部类访问局部变量必须用final修饰
B:为什么呢?
局部变量是随着方法的调用而调用,随着调用完毕而消失。而堆内存的内容并不会立即消失。所以,我们加final修饰。加入final修饰后,这个变量就成了常量。

class Outer {
    private int num  = 10;

    public void method() {
        //int num2 = 20;
        //final int num2 = 20;
        class Inner {
            public void show() {
                System.out.println(num);
                //从内部类中访问本地变量num2; 需要被声明为最终类型
                System.out.println(num2);//20
            }
        }

        //System.out.println(num2);

        Inner i = new Inner();
        i.show();
    }
}

class InnerClassDemo5 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

匿名内部类
就是内部类的简化写法。

前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。

格式:
new 类名或者接口名(){
重写方法;
}

本质
是一个继承了该类或者实现了该接口的子类匿名对象。

interface Inter {
    public abstract void show();
    public abstract void show2();
}

class Outer {
    public void method() {
        Inter i = new Inter() { //多态
            public void show() {
                System.out.println("show");
            }

            public void show2() {
                System.out.println("show2");
            }
        };

        i.show();
        i.show2();
    }
}

class InnerClassDemo6 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

总结

面向对象是Java最重要的内容,以后所有的知识都是围绕着面向对象展开的,可以说,没有面向对象,以后学习的功能都无法使用。

——- android培训java培训、期待与您交流! ———-

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Sherlock_Li/article/details/48108513

智能推荐

js-选项卡原理_选项卡js原理-程序员宅基地

文章浏览阅读90次。【代码】js-选项卡原理。_选项卡js原理

设计模式-原型模式(Prototype)-程序员宅基地

文章浏览阅读67次。原型模式是一种对象创建型模式,它采用复制原型对象的方法来创建对象的实例。它创建的实例,具有与原型一样的数据结构和值分为深度克隆和浅度克隆。浅度克隆:克隆对象的值类型(基本数据类型),克隆引用类型的地址;深度克隆:克隆对象的值类型,引用类型的对象也复制一份副本。UML图:具体代码:浅度复制:import java.util.List;/*..._prototype 设计模式

个性化政府云的探索-程序员宅基地

文章浏览阅读59次。入选国内首批云计算服务创新发展试点城市的北京、上海、深圳、杭州和无锡起到了很好的示范作用,不仅促进了当地产业的升级换代,而且为国内其他城市发展云计算产业提供了很好的借鉴。据了解,目前国内至少有20个城市确定将云计算作为重点发展的产业。这势必会形成新一轮的云计算基础设施建设的**。由于云计算基础设施建设具有投资规模大,运维成本高,投资回收周期长,地域辐射性强等诸多特点,各地在建...

STM32问题集之BOOT0和BOOT1的作用_stm32boot0和boot1作用-程序员宅基地

文章浏览阅读9.4k次,点赞2次,收藏20次。一、功能及目的 在每个STM32的芯片上都有两个管脚BOOT0和BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序。BOOT1=x BOOT0=0 // 从用户闪存启动,这是正常的工作模式。BOOT1=0 BOOT0=1 // 从系统存储器启动,这种模式启动的程序_stm32boot0和boot1作用

C语言函数递归调用-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏22次。C语言函数递归调用_c语言函数递归调用

明日方舟抽卡模拟器wiki_明日方舟bilibili服-明日方舟bilibili服下载-程序员宅基地

文章浏览阅读410次。明日方舟bilibili服是一款天灾驾到战斗热血的创新二次元废土风塔防手游,精妙的二次元纸片人设计,为宅友们源源不断更新超多的纸片人老婆老公们,玩家将扮演废土正义一方“罗德岛”中的指挥官,与你身边的感染者们并肩作战。与同类塔防手游与众不同的几点,首先你可以在这抽卡轻松获得稀有,同时也可以在战斗体系和敌军走位机制看到不同。明日方舟bilibili服设定:1、起因不明并四处肆虐的天灾,席卷过的土地上出..._明日方舟抽卡模拟器

随便推点

Maven上传Jar到私服报错:ReasonPhrase: Repository version policy: SNAPSHOT does not allow version: xxx_repository version policy snapshot does not all-程序员宅基地

文章浏览阅读437次。Maven上传Jar到私服报错:ReasonPhrase: Repository version policy: SNAPSHOT does not allow version: xxx_repository version policy snapshot does not all

斐波那契数列、素数、质数和猴子吃桃问题_斐波那契日-程序员宅基地

文章浏览阅读1.2k次。斐波那契数列(Fibonacci Sequence)是由如下形式的一系列数字组成的:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …上述数字序列中反映出来的规律,就是下一个数字是该数字前面两个紧邻数字的和,具体如下所示:示例:比如上述斐波那契数列中的最后两个数,可以推导出34后面的数为21+34=55下面是一个更长一些的斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,_斐波那契日

PHP必会面试题_//该层循环用来控制每轮 冒出一个数 需要比较的次数-程序员宅基地

文章浏览阅读363次。PHP必会面试题1. 基础篇1. 用 PHP 打印出前一天的时间格式是 2017-12-28 22:21:21? //>>1.当前时间减去一天的时间,然后再格式化echo date('Y-m-d H:i:s',time()-3600*24);//>>2.使用strtotime,可以将任何字符串时间转换成时间戳,仅针对英文echo date('Y-m-d H:i:s',str..._//该层循环用来控制每轮 冒出一个数 需要比较的次数

windows用mingw(g++)编译opencv,opencv_contrib,并install安装_opencv mingw contrib-程序员宅基地

文章浏览阅读1.3k次,点赞26次,收藏26次。windows下用mingw编译opencv貌似不支持cuda,选cuda会报错,我无法解决,所以没选cuda,下面两种编译方式支持。打开cmake gui程序,在下面两个框中分别输入opencv的源文件和编译目录,build-mingw为你创建的目录,可自定义命名。1、如果已经安装Qt,则Qt自带mingw编译器,从Qt安装目录找到编译器所在目录即可。1、如果已经安装Qt,则Qt自带cmake,从Qt安装目录找到cmake所在目录即可。2、若未安装Qt,则安装Mingw即可,参考我的另外一篇文章。_opencv mingw contrib

5个高质量简历模板网站,免费、免费、免费_hoso模板官网-程序员宅基地

文章浏览阅读10w+次,点赞42次,收藏309次。今天给大家推荐5个好用且免费的简历模板网站,简洁美观,非常值得收藏!1、菜鸟图库https://www.sucai999.com/search/word/0_242_0.html?v=NTYxMjky网站主要以设计类素材为主,办公类素材也很多,简历模板大部个偏简约风,各种版式都有,而且经常会更新。最重要的是全部都能免费下载。2、个人简历网https://www.gerenjianli.com/moban/这是一个专门提供简历模板的网站,里面有超多模板个类,找起来非常方便,风格也很多样,无须注册就能免费下载,_hoso模板官网

通过 TikTok 联盟提高销售额的 6 个步骤_tiktok联盟-程序员宅基地

文章浏览阅读142次。你听说过吗?该计划可让您以推广您的产品并在成功销售时支付佣金。它提供了新的营销渠道,使您的产品呈现在更广泛的受众面前并提高品牌知名度。此外,TikTok Shop联盟可以是一种经济高效的产品或服务营销方式。您只需在有人购买时付费,因此不存在在无效广告上浪费金钱的风险。这些诱人的好处是否足以让您想要开始您的TikTok Shop联盟活动?如果是这样,本指南适合您。_tiktok联盟