类与对象(二)

目录

代码块的定义与使用:

1.普通代码块

2.构造块

3.静态代码块

4.同步代码块

继承的定义与使用:

1.继承的实现

2.继承的限制

覆写:

super关键字:

1.super用于方法

2.super用于属性

final关键字:

1.final修饰类(String类以及8大基本数据类型的包装类,Integer)

2.final修饰方法

3.final修饰变量

多态性:

1.方法的多态性

2.对象的多态性

内部类的定义与使用:

1.内部类的优缺点

2.内部类与外部类的关系

3.创建内部类语法

4.内部类的分类

5.内部类的特点


代码块的定义与使用:

定义:使用“{ }”定义的一段代码。

根据代码块定义的位置以及关键字,可以分为以下四种:

1.普通代码块

2.构造块

3.静态代码块

4.同步代码块

1.普通代码块

定义在方法中的代码块。

2.构造块

定义在类中的代码块(不加修饰符)。

举个栗子:

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

public class Test{
    public static void main(String[] args){
        A a1 = new A();
        A a2 = new A();
    }
}

运行结果:

通过上述代码我们发现:在对象产生时,构造块优先于构造方法执行,有几个对象产生,就调用几次构造块。构造块可以完成一些属性的初始化操作(在调用构造方法前)。

3.静态代码块

使用static定义的代码块。

根据静态块所在的类不同,可以分为以下两种类型:

1.在非主类中

2.在主类中

3.1在非主类中的静态代码块

举个栗子:

class A{
    public A(){
        System.out.println("这是构造方法");
    }
    {
        System.out.println("这是构造块");
    }
    static{
        System.out.println("这是静态块");
    }
}

public class Test{
    public static void main(String[] args){
        System.out.println("-----start-----");
        A a1 = new A();
        A a2 = new A();
        System.out.println("-----end-----");
    }
}

运行结果:

通过上述代码我们发现:静态代码块在类加载时执行,优先于构造块执行,无论有多少对象产生,只会调用一次。

静态块的主要作用是为static属性进行初始化。

3.2在主类中的静态代码块

举个栗子:

public class Test{
    {
        System.out.println("主类的构造块");
    }
    static{
        System.out.println("主类的静态块");
    }
    public Test(){
        System.out.println("主类的构造方法");
    }
    public static void main(String[] args){
        System.out.println("-----start-----");
        A a1 = new A();
        A a2 = new A();
        System.out.println("-----end-----");
    }
}

运行结果:

通过上述代码我们可以发现:在主类中定义的代码块,优先于主方法执行。

4.同步代码块

与线程同步问题有关,在此不多加阐述。

代码块的基本知识都已经明白了,接下来我们看一道习题,结合了上述所有知识点。可以自己想想答案是什么。



class HelloA{
public HelloA(){
System.out.println("这是父类的构造方法");
}
{
System.out.println("这是父类的非静态代码块");
}
static{
System.out.println("这是父类的静态代码块");
}
}

class HelloB extends HelloA{
public HelloB(){
System.out.println("这是子类的构造方法");
}
{
System.out.println("这是子类的非静态代码块");
}
static{
System.out.println("这是子类的静态代码块");
}
}

public class Test{
public static void main(String[] args){
System.out.println("-----start-----");
new HelloB();
new HelloB();
System.out.println("-----end-----");
}
}

继承的定义与使用:

1.继承的实现

在Java中,继承使用extends关键字来实现。定义的语法如下:

class 子类 extends 父类

注:子类又时也被称为派生类,父类也被称为超类或基类。

在发生了类的继承关系后,子类可以直接继承父类的操作,实现代码的重用。

子类最低也维持和父类相同的功能。

子类可以进行功能上的扩充。

2.继承的限制

子类对象实例化前,首先调用父类构造方法产生父类对象后,再调用子类构造方法实例化子类对象。

举个栗子:

class Person{
    public Person(){
        System.out.println("父类对象产生");
    }
}

class Student extends Person{
    public Student(){
        super();//此语句在无参时写与不写都一样
        System.out.println("子类对象产生");
    }
}

public class Test{
    public static void main(String[] args){
       new Student();
    }
}

运行结果:

注:实际上在子类的构造方法中,相当于隐含了一条语句,super( );如果父类中没有提供无参构造,就必须使用super( )明确指明你要调用的构造方法。

Java只允许单继承,不允许多继承。(Java的单继承局限)

要想在Java中实现类似的“多继承”,要么多层继承,要么使用内部类。

//多层继承
class A(){}
class B extends A(){}
class C extends B(){}

多层继承层数不建议太多,最好不要超过3层。

在继承时,子类会继承父类的所有结构。(包含私有域与其他属性,方法)

显式继承:所有非私有操作(非private操作)属于显式继承(可以直接调用)

隐式继承:所有私有操作(private操作)属于隐式继承(不可以直接调用,需要通过其他形式调用,例如getter,setter)

覆写:

定义:子类定义了与父类方法名称,参数列表,返回值完全相同的方法。被覆写的方法不能拥有比父类更为严格的访问控制权限。

private < default < protected < public

举个栗子:

class Person{
    public void print(){
        System.out.println("父类的print方法");
    }
}

class Student extends Person{
   public void print(){
       System.out.println("子类的print方法");
   }
}

public class Test{
    public static void main(String[] args){
     new Student().print();
    }
}

运行结果:

以后在进行覆写操作的时候,要注意以下两点:

a.看new在哪(当前使用的对象是通过哪个类new的)

b.调用的方法有没有被子类覆写,如果被覆写,调用的一定是被覆写后的方法。

覆写和重载的区别:

区别重载(overload)覆写(override)
概念方法名称相同,参数的类型及个数不同方法名称,返回值类型,参数的类型及个数完全相同
范围一个类继承关系
限制没有权限要求被覆写的方法不能拥有比父类更为严格的访问控制权限

super关键字:

1.super用于方法

a.用于构造方法

表示调用父类构造方法。

语法:super (参数列表)

I. 当子类调用父类无参构造时,super( )可写可不写,表示调用父类无参构造。

II. 当子类调用父类有参构造时,super(参数列表)必须要写,要告诉编译器当前调用的是哪个有参构造。

注意:

(1)子类构造方法中调用父类构造必须是第一行语句

(2)this与super不能同时调用

b.用于普通方法

语法:super.方法名(参数)

用于在子类中明确调用父类被覆写的方法。

举个栗子:

class Person{
    private String name;
    public Person(String name){
        this.name = name;
        System.out.println("父类的有参构造");
    }
    public void print(){
        System.out.println("父类的print方法");
    }
}

class Student extends Person{
    public Student(){
        super("li");//super用于构造方法
        System.out.println("子类的无参构造");
    }
   public void print(){
       super.print();//super用于普通方法
       System.out.println("子类的print方法");
   }
}

public class Test{
    public static void main(String[] args){
     new Student().print();
    }
}

运行结果:

2.super用于属性

super.属性名 

表示调用父类中被覆写的属性

final关键字:

1.final修饰类(String类以及8大基本数据类型的包装类,Integer)

a.当一个类被final关键字修饰,表示该类不能拥有子类(该类不允许被继承)。

b.一旦一个类被final修饰,该类的所有方法都会默认加上final。

2.final修饰方法

当一个方法被final修饰,明确表示该方法不能被覆写。

3.final修饰变量

I.final修饰普通数据类型的成员变量

被final修饰的成员变量必须在声明时初始化(构造块或构造方法中初始化),并且初始化后值无法被修改。

II.final修饰引用数据类型的变量

其引用不可变,即不能再指向其他的对象。

多态性:

1.方法的多态性

a.方法的重载:同一个方法名称可以根据参数的类型或个数不同,调用不同的方法体。

b.方法的覆写:同一个父类的方法,可能根据实例化子类的不同也有不同的实现。

2.对象的多态性

a.对象的向上转型:用于参数统一化

语法:父类 父类引用 = new 子类();

不管是否发生了向上转型,其核心本质还在于:你使用的是哪一个子类(new在哪里),而且调用的方法是否被子类覆写了。

b.向下转型:当父类引用需要调用子类扩充方法时,才需要向下转型

语法:子类 子类引用 = (子类)父类引用;

注:要发生向下转型,必须先发生向上转型

举个栗子:

class Person{
    public void print(){
        System.out.println("我是父类方法");
    }
}

class Student extends Person{
    public void print(){
        System.out.println("我是子类方法");
    }
    public void fun(){
        System.out.println("只有子类有");
    }
}

public class Test{
    public static void main(String[] args){
        Person per = new Student();//向上转型
        per.print();
        System.out.println("-----------------------");
        //这个父类能够调用的方法只能是本类定义好的方法
        //所以并没有子类中的dun()方法,那么只能向下转型
        Student stu = (Student) per;//向下转型
        stu.fun();
    }
}

运行结果:

内部类的定义与使用:

内部类:在类内部进行其他类结构嵌套操作。

1.内部类的优缺点:

内部类的优点:

a.内部类与外部类可以方便的访问彼此的私有域(包括私有方法,私有属性)

b.内部类是另外一种封装(保护性),对外部的其他类隐藏

c.内部类可以实现Java单继承的局限

缺点:

结构复杂

2.内部类与外部类的关系:

a.对于非静态内部类,内部类的创建需要依赖外部类对象,在没有外部类实例之前无法创建非静态内部类。

b.内部类是一个相对独立的个体,与外部类没有is--a关系。

c.内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类元素,需要通过内部类的引用间接访问

3.创建内部类语法

a.在外部类外部创建非静态内部类

外部类.内部类 内部类引用 = new 外部类().new 内部类();

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

b.在外部类外部创建静态内部类

外部类.内部类 内部类引用 = new 外部类.内部类( );

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

4.内部类的分类

I.成员内部类(类比成员方法)

a.成员内部类内部不能存在任何static变量或方法,可以访问外部类的静态域

b.成员内部类是依附外部类的,所有只有先创建了外部类,才能创建内部类。

II.静态内部类(类比静态方法)

a.静态内部类的创建不需要依赖外部类,可以直接创建

b.静态内部类不可以使用任何外部类的非static域(包含属性与方法),但是可以存在自己的成员变量

举个栗子:

class Outter{
    private static String msg = "Hello World";
    //定义一个内部类
    static class Inner{
        public void print(){
            //只能使用外部类的静态属性
            System.out.println(msg);
        }
    }
    //在外部类定义一个方法,负责产生内部类对象并且调用print方法
    public void fun(){
        Inner in = new Inner();//内部类对象
        in.print();//内部类提供的print方法
    }
}

public class Test{
    public static void main(String[] args){
        Outter.Inner in = new Outter.Inner();
        in.print();
    }
}

运行结果:

III.方法内部类(局部内部类)

  a.方法内部类不允许使用访问权限修饰符 public、private、protected

  b.方法内部类对外部完全隐藏,除了创建这个类的方法可使用以外,其他地方均不能访问

  c.方法内部类如果要想使用方法形参,该形参必须使用final声明(JDK8将形参变为隐式final声明)

IV.匿名内部类(lamdba表达式前身)

匿名内部类就是一个没有名字的方法内部类。因此特点与方法内部类完全一样,除此之外还有两个自己的特点:

    a.匿名内部类必须继承一个抽象类或者实现一个接口

    b.匿名内部类没有构造方法,因为它没有类名

举个栗子:

interface MyInterface{
    void test();
}

class Outter{
    private int num;
    public void display(int para){
        //匿名内部类,实现了MyInterface接口
        new MyInterface(){
        
            @Override
            public void test() {
                System.out.println("匿名内部类"+para);
            }
        }.test();
    }
}

public class Test{
    public static void main(String[] args){
        Outter outter = new Outter();
        outter.display(20);
    }
}

运行结果:

5.内部类的特点

a.破坏了程序的结构

b.方便进行私有属性的访问。(外部类也可以访问内部类的私有结构)

c.如果发现类名称出现了“.”,应当 立即想到内部类的概念

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值