黑马程序员--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

智能推荐

初试 Kubernetes 动态卷配置使用 RBD 作为 StorageClass_failed to provision volume with storageclass-程序员宅基地

文章浏览阅读3.7k次。目录Kubernetes StorageClass 介绍环境、软件准备Kubernetes 使用 RBD 作为 StorageClass1、Kubernetes StorageClass 介绍Kubernetes 集群存储 PV 支持 Static 静态配置以及 Dynamic 动态配置,动态卷配置 (Dynamic provisioning) 可以根据需要动态的创建存储卷。我们知道,之前的静态配..._failed to provision volume with storageclass

三元组存放的稀疏矩阵的转置_三元组存储稀疏矩阵进行转置-程序员宅基地

文章浏览阅读1.7k次。稀疏矩阵: 非零元素很少,但是分布没有规律的矩阵。(即可以用三元组来存放每个非零元)。三元组顺序表的定义:#define size 3typedef int Elemtype;typedef struct{ int i,j;//非零元的行,列 Elemtype e;//非零元元素 }Triple;//三元组 typedef struct{ Triple date[size+1]..._三元组存储稀疏矩阵进行转置

java判断熟数字_java大牛须知道的25点-程序员宅基地

文章浏览阅读49次。1. 你需要精通面向对象分析与设计(OOA/OOD)、涉及模式(GOF,J2EEDP)以及综合模式。你应该了解UML,尤其是class、object、interaction以及statediagrams.2. 你需要学习Java语言的基础知识以及它的核心类库(collections、serialization、streams、networking、multithreading、reflection..._熟门熟码是什么数字

在DOS下输入C:fdisk/mbr 是什么意思?-程序员宅基地

文章浏览阅读543次。Fdisk是我们在硬盘分区时最常用的命令,但有的读者可能还不知道,Fdisk命令还有一个未公开参数/MBR,如果在DOS提示符下使用Fdisk /?不会发现此参数,但是这个参数却有很重要的作用,MBR是主引导记录(Master Boot Record)的缩写。那么,Fdisk /MBR是如何工作的呢?下面和各位读者共同学习一下。 先来看看主引导扇区,硬盘的零柱面零磁道..._在dos下用fdisk/mbr命令进行修复

QT基于RFID管理系统(可应用于大多数RFID管理系统)_rfid读卡qt设计-程序员宅基地

文章浏览阅读1.5k次,点赞3次,收藏16次。本系统由QT编译,可应用于大多数基于RFID的管理系统,可进行端口设置,进出系统物品查询等基本功能!系统实现:将RFID技术引入柜台贵重物品管理系统,为贵重的柜台商品绑定RFID标签,结合安装在柜台上的RFID识别设备用来监测、控制和跟踪贴标的贵重物品,实现快速盘点、实时跟踪及销售的智能管理。从而对柜台贵重物品产品的进出和销售过程进行全方位的跟踪和记录,用自动化和准确高效的新方法取代了繁琐和低效的人工管理和条码扫描模式。并能做到短距离离开柜台(3~5米)报警,未能取得授权情况下,破坏或解除RFID标签与贵重_rfid读卡qt设计

具体数学 递归问题1.1 从河内塔/汉诺塔开始_任意起始的汉诺塔问题:共有m()根柱子可以用来移动盘子。起始时,在m根柱子上总-程序员宅基地

文章浏览阅读652次。河内塔问题在经典河内塔问题中,有3根柱子和N个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按从大到小依次套在一根柱子上,现在想将所有的圆盘按照原来的位置从一根柱子移动到另一根柱子上,移动过程需要遵守一些规则:1.每次只能移动一个盘子2.盘子只能从柱子顶端滑出移动到下一根柱子3.盘子只能叠在没有盘子的柱子或者比它大的盘子上聚焦河内塔问题。河内塔的规则,限定了较大的圆盘要先转移到目标柱子(选择的任意一根柱子)上,这时直接转移是不可行的,一定要利用其他柱子。问题中只有3根柱_任意起始的汉诺塔问题:共有m()根柱子可以用来移动盘子。起始时,在m根柱子上总

随便推点

MSYS2安装和使用_pacman windows-程序员宅基地

文章浏览阅读546次,点赞14次,收藏12次。msys2是一款跨平台编译套件,它模拟linux编译环境,支持整合mingw32和mingw64,能很方便的在windows上对一些开源的linux工程进行编译运行。更重要的是它支持pacman包管理器;这意味着你可以很方便的安装所需要的软件包和开发库,而不需要自己去找源码编译。_pacman windows

JDK8 日期格式化_jdk date pattern-程序员宅基地

文章浏览阅读1w次。为什么要格式化我们中国人习惯 yyyy-MM-dd HH:mm:ss 这种格式的日期,但奈何框架是歪国大佬们写的,他们的日期格式与我们相差甚远,好在 Spring Boot 提供了 spring.jackson.date-format,但它只能格式化 java.util.Date。那么解决办法是什么呢?在 JDK8 中,一个新的重要特性就是引入了全新的时间和日期API,它被收录在 java..._jdk date pattern

不是python中用于开发用户界面的第三方库-Python计算生态习题(50题)-程序员宅基地

文章浏览阅读6k次,点赞3次,收藏36次。1、Python网络爬虫方向的第三方库是A. requestB. jiebaC.itchatD.time答案:A2、Python网络爬虫方向的第三方库是A、numpyB、scrapyC、ArcadeD、FGMK答案:B3、Python数据分析方向的第三方库是A、BokehB、dataswimC、scipyD、Gleam答案:C4、Python数据分析方向的第三方库是A、PlotlyB、PyQtDa..._python第三方库习题

线程的状态-Thread的状态包括:New、Runnable、Blocked、Waiting、Timed Waiting和Terminated_thread terminated-程序员宅基地

文章浏览阅读544次。在Java程序中,一个线程对象只能调用一次start()方法启动新线程,并在新线程中执行run()方法。一旦run()方法执行完毕,线程就结束了。因此,Java线程的状态有以下几种:New:新创建的线程,尚未执行; Runnable:运行中的线程,正在执行run()方法的Java代码; Blocked:运行中的线程,因为某些操作被阻塞而挂起; Waiting:运行中的线程,因为某些操作在等待中; Timed Waiting:运行中的线程,因为执行sleep()方法正在计时等待; Termina_thread terminated

【AI视野·今日CV 计算机视觉论文速览 第259期】Tue, 3 Oct 2023_humannorm: learning normal diffusion model for hig-程序员宅基地

文章浏览阅读543次。AI视野·今日CS.CV 计算机视觉论文速览Tue, 3 Oct 2023 (showing first 100 of 167 entries)Totally 100 papers上期速览更多精彩请移步主页Daily Computer Vision PapersGPT-Driver: Learning to Drive with GPT Authors Jiageng Mao, Yuxi Qian, Hang Zhao, Yue Wang我们提出了一种简单而有效的方法,可以将 O_humannorm: learning normal diffusion model for high-quality and realistic 3d

vivado仿真器文件没有针对VCS的,这个时候将ip文件夹下的sim 和simulation文件夹给到VCS就可以_vivado不支持vcs-程序员宅基地

文章浏览阅读1k次。这个时候将ip文件夹下的sim 和simulation文件夹给到VCS就可以_vivado不支持vcs

推荐文章

热门文章

相关标签