首页 > 编程语言 >JavaSE——类与对象(5)

JavaSE——类与对象(5)

时间:2024-12-01 15:29:20浏览次数:8  
标签:内部 对象 void 接口 class new JavaSE public

一、抽象类

1.1为什么需要抽象类

        父类的某些方法,不确定怎么实现,也不需要实现。

class Animal{
    public String name;
    
    public Animal(String name){
        this.name = name;
    }

    public void eat()//这里实现了也没有意义
    {
        System.out.println("这是一个动物,但是不知道吃什么..");
    }
}

        像上面这个例子,属于一个父类方法不确定性问题,可以考虑将这个方法设计为抽象方法。所谓的抽象方法就是没有实现的方法,没有实现的方法就是没有方法体,当一个类中存在抽象方法时,需要将这个类声明为抽象类。一般来讲,抽象类会被继承,由其子类来实现抽象方法。

1.2抽象类的细节

  1. 抽象类不能被实例化
  2. 抽象类不一定要包含abstract方法,也就是说,抽象类可以没有abstract方法
  3. 一旦类包含了abstract方法,那么这个类必须时abstract类。
  4. abstract只能修饰类和方法,不能修饰属性和其它的。
  5. 抽象类可以拥有任意成员,抽象类的本质还是类
  6. 如果一个类继承了抽象类,则它必须实现抽象类的所有方法,除非它自己也声明为抽象类。
  7. 抽象方法,不能使用private、final和static来修饰。

二、接口

2.1接口的基本介绍

        接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。

定义的基本语法:

interface 接口名{
    属性
    方法
}

调用的基本语法:

class 类名 implements 接口{
    自己属性;
    自己方法;
    必须实现的接口的方法;
}

         在JDK7以前,接口中的所有方法都是抽象方法,在JDK7以后的版本中,可以有静态方法和默认方法。另外接口不需要声明为抽象类。

2.2接口的使用细节

  1. 接口不能被实例化。
  2. 接口中的所有方法都是public方法,即使没有使用public修饰符,它也是public的。
  3. 接口中抽象方法,可以不用abstract修饰。
  4. 一个普通类上实现接口,必须将该接口的所有方法都实现
  5. 抽象类实现接口,可以不用实现接口的方法。
  6. 一个类允许实现多个接口。
  7. 接口中的属性,只能是final的,而且默认是public static final修饰符。
  8. 接口中属性的访问形式:接口名.属性名。
  9. 一个接口不能继承其它类,但是可以继承多个别的接口
  10. 接口的修饰符只能是public和默认。

2.3接口与继承

  1. 继承和接口解决的问题不同:
    1. 继承的价值在于:解决代码的复用性和可维护性。
    2. 接口的价值在于:设计好各种规范和方法,让其它类去实现这些方法。
  2. 接口比继承更加灵活,可以说是对Java单继承方式的一种补充,继承满足is-a关系,接口只需要满足like-a关系。
  3. 接口在一定程度上实现代码解耦。

2.4接口的多态特性

  1. 多态参数:接口引用可以指向实现了接口的类的对象。
    public class Interface01{
        public static void main(String[] args) {
            IH ih = new A();
            IG ig = new A();
        }
    }
    
    interface IH{}
    interface IG{}
    
    class A implements IH{}
  2. 多态数组:多态性允许一个引用类型指向多种实际类型的对象。这种特性在处理数组时尤为有用,因为数组可以存储指向不同子类对象的引用,即使数组的声明类型是父类类型。
  3. 接口存在多态传递现象
    public class Interface01{
        public static void main(String[] args) {
            IH ih = new A();
            IG ig = new A();
        }
    }
    
    interface IH{}
    interface IG{}
    //interface IH extends IG{};A实现IH的同时把IG也实现了
    
    class A implements IH{}

三、内部类

3.1什么是内部类

        一个类的内部完整的嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其它类的类被称为外部类。一个内部类:

class Outer{//外部类
    private int i = 100;//属性
    public Outer(int n1){//构造器
        this.i = n1;
    }

    public void m1(){//方法
        System.out.println("m1()");
    }
    {//代码块
        System.out.println("代码块...");
    }

    class Inner{//内部类
    }
}

3.2内部类的分类

定义在外部类局部位置上(比如方法内):

  1. 局部内部类(没有类名)
  2. 匿名内部类(没有类名)

定义在外部类的成员位置上:

  1. 成员内部类(未用static修饰)
  2. 静态内部类(使用static修饰)

3.3局部内部类

        局部内部类定义在外部类的局部位置,比如方法中,并且有类名。

class Outer{//外部类
    private int i = 100;//属性
    public Outer(int n1){//构造器
        this.i = n1;
    }

    public void m1(){//方法
        System.out.println("m1()");
    }
    {//代码块
        System.out.println("代码块...");
    }

    public void m2(){
        class Inner{ //不能添加访问修饰符,因为它是一个局部变量,局部变量不能使用修饰符。
                     //但是可以用final修饰
            public void m3(){
                System.out.println(i);//可以直接访问外部类的所有成员,包含私有的。
            }
        }
        Inner i = new Inner();//外部类访问内部类,先创建对象再访问,必须在作用域内。
        i.m3();
    }
}

总结:

  1. 内部类可以直接访问外部类的所有成员,包括私有的
  2. 外部类访问内部类的成员需要先创建内部类的对象,再访问,并且必须在作用域内部
  3. 作用域:仅仅在定义它的方法或者代码块中。
  4. 除final之外不能使用访问修饰符。
  5. 局部内部类本质是一个类也可以被继承。
  6. 如果外部类和内部类的成员重名,默认遵循就近原则,如果想要访问外部类的成员,使用外部类名.this.变量名

3.4匿名内部类

        匿名内部类是定义在外部类的局部位置,没有名字的类(其实有,只不过是由编译器取的,程序员看不见也不能干涉)。 

        假设我们有一个接口A,内部有一个未被实现的方法eat,如果想要在main中直接调用eat方法,按照传统思路是先用一个类来实现接口A,同时再创建B的对象来调用A。

public class Interface01 {
    public static void main(String[] args) {
        B b = new B();
        b.eat();
    }
}
interface A{
    public void eat();
}
class B implements A{
    @Override
    public void eat() {
        System.out.println("正在调用eat方法");
    }
}

        但是,如果这个方法只会实现一次,如果为此单独写一个类还要再创建对象的化,未免有些古板,这里就可以采用匿名内部类

public class Interface01 {
    public static void main(String[] args) {
        new A(){
            @Override
            public void eat() {
                System.out.println("正在调用eat方法");
            }
        }.eat();
    }
}
interface A{
    public void eat();
}

        这是的匿名内部类相当于一个对象,所以它的后面可以直接调用eat方法。当A里面有多个方法时,如果想要同时调用,可以采用下面的方法。

public class Interface01 {
    public static void main(String[] args) {
        //编译器创建了一个类继承了A类,并且在内部重写了下面这些方法。
        //编译类型是A,运行类型是Interface01$1
        A a = new A(){
            @Override
            public void eat() {
                System.out.println("正在调用eat方法");
            }
            public void drink(){
                System.out.println("正在调用drink方法");
            }
        };
        a.eat();
        a.drink();
    }
}
interface A{
    public void eat();
    public void drink();
}

匿名内部类常用做实参进行传递:

public class InnerClassExercise {
    public static void main(String[] args) {
        Cellphone cellphone = new Cellphone();
        cellphone.alarmlock(new Bell(){
            @Override
            public void ring() {
                System.out.println("懒猪起床了");
            }
        });

        Bell innerclass = new Bell(){
            @Override
            public void ring() {
                System.out.println("小伙伴上课了");
            }
        };

        cellphone.alarmlock(innerclass);

    }
}

interface Bell{
    void ring();
}

class Cellphone{
    public void alarmlock(Bell bell){
        bell.ring();
    }
}

总结:

  1. 匿名内部类本身既是一个类的定义,也是一个对象,所以从语法上看,它既有定义类的特征,也有创建对象的特征。
  2. 可以直接访问外部类的所有成员,包含私有的。
  3. 不能直接添加访问修饰符,因为他的地位就是一个局部变量。
  4. 作用域:仅仅再定义它的方法内部或者代码块中。
  5. 外部的其它类不能访问内部匿名类。
  6. 如果外部类和匿名内部类的成员重名,默认遵循就近原则,也可以通过(外部类名.this.成员名)去访问。

3.5成员内部类

        成员内部类是定义再外部类的成员位置,并且没有static修饰。

public class MemberInnerClass01 {
    public static void main(String[] args) {
        Outer01 outer01 = new Outer01();
        outer01.t1();
    }
}

class Outer01{
    private int a = 10;
    public String name = "张三";

    class InnerClass{
        public void say()
        {//可以直接访问外部类的成员
            System.out.println("Outer01的a = " + a + "\tOuter01的name + " + name);
        }

    }
    public void t1(){
        InnerClass innerClass = new InnerClass();
        innerClass.say();
    }
}

总结: 

  1. 可以直接访问外部类的所有成员,包含私有的。
  2. 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位是一个成员。
  3. 作用域:和外部域的其他成员一样,为整个类体比如前面案例。在外部类的成员方法中创建成员内部类对象,再调用方法
  4. 成员内部类访问外部类成员:直接访问。
  5. 外部类访问成员内部类:先创建对象,再访问。

外部其它类访问成员内部类:

  1. 可以依托这样的语法:
    OuterClass.InnerClass inner = OuterClass.new InnerClass()
  2. 在外部类中编写一个方法返回一个成员内部类的对象。
public class MemberInnerClass01 {
    public static void main(String[] args) {
          Outer01 outer01 = new Outer01();
          Outer01.InnerClass inner01 = outer01.new InnerClass();
          inner01.say();
          Outer01.InnerClass inner02 = outer01.getInnerClass();
          inner02.say();
    }
}

class Outer01{
    private int a = 10;
    public String name = "张三";

    class InnerClass{
        int a = 20;
        public void say()
        {
            System.out.println("Outer01的a = " + a + "\tOuter01的name + " + name);
        }
    }
    public InnerClass getInnerClass(){
        return new InnerClass();
    }
}

3.6静态内部类

        静态内部类定义在外部类的成员位置,并且有static修饰。

public class StaticInnerClass {
    public static void main(String[] args) {
        Outer outer = new Outer();
        //使用固定的语法
        Outer.Inner inner1 = new Outer.Inner();
        inner1.say();
        System.out.println("----------");
        //编写一个函数,返回静态内部类的对象实例
        Outer.Inner inner2 = outer.getInner();
        inner2.say();
        System.out.println("----------");
        //静态函数版本
        Outer.Inner inner3 = Outer.getInner_();
        inner3.say();
    }
}

class Outer {
    private int n1 = 10;
    private static int n2 = 20;
    public static class Inner{//可以添加访问修饰符
        public void say(){
            //System.out.println(n1);//报错,不能访问非静态成员
            System.out.println(n2);//正确。
        }
    }
    public Inner getInner(){
        return new Inner();
    }

    public static Inner getInner_() {//静态版本
        return new Inner();
    }
}

总结:

  1. 可以直接访问外部类的所有静态成员,包含私有的,但是不能直接访问非静态成员。
  2. 可以添加任意访问修饰符,因为它的低位就是一个成员。
  3. 作用域:等同于其他成员,为整个类体。
  4. 静态内部类访问外部类:直接访问。
  5. 外部类访问静态内部类:创建对象在访问。
  6. 外部其它类访问静态内部类:
    1. 使用语法进行访问:
      Outer.Inner inner1 = new Outer.Inner();
    2. 编写一个函数,返回内部类的一个对象。函数可以有static版本。
  7. 当与外部类成员重名时,采用外部类名.成员来访问。

 

 

 

               

 

        

标签:内部,对象,void,接口,class,new,JavaSE,public
From: https://blog.csdn.net/qq_55890817/article/details/144146446

相关文章

  • java的Webclient对象怎解解析400状态码
    在Java中使用WebClient处理400状态码,可以通过检查响应状态并根据状态码进行相应的错误处理。以下是几种处理400状态码的方法:使用onStatus方法判断和处理错误:你可以使用WebClient的retrieve()方法链中的onStatus方法来检查响应状态码。如果状态码为400,你可以打印错误信息......
  • Javascript遍历目录时使用for..in循环无法获取Files对象和SubFolders对象问题的解决方
      1Javascript遍历目录时使用for..in循环无法获取Files对象和SubFolders对象1.1问题场景  在JavaScript中遍历目录,使用for..in循环时,无法获取到Files对象和SubFolders对象,导致无法遍历目录和子目录。  代码如下:functionGetAllFilesInSubFolder(path,filter)......
  • 从源码角度深入剖析Spring Bean对象创建过程中各后置处理器的作用与实现原理
            springioc容器刷新的过程中涵盖了bean对象的创建流程,再bean对象创建的过程中,使用了哪些后置处理器(扩展接口)?这些后置处理器又有什么作用?下图为spring容器刷新过程中,各处理器的位置。        本文着重对BeanDefinitionRegistryPostProcessor、MergedB......
  • SQLalchemy中Query对象使用
    SQLAlchemy中Query对象的使用前言一、表结构的声明和数据的插入二、使用1.过滤,分组,排序的使用1.1过滤(filter)使用1.2分组(group_by)的使用1.3排序(order_by)的使用2.去重,合并的使用2.1去重(distinct)2.2合并3.连接4.切片,分页。5.快捷方式总结前言Query对象是S......
  • Java--面向对象三大特征多态
    目录概念多态调用成员的特点多态的优势和弊端概念多种形态,完成某个行为,当不同的对象去完成时会产生出不同的状态,简而言之,同类型的对象,表现出不同状态及对象的多种形态其好处是使用父类作为参数,可以接收所有子类对象,体现了多态的扩展性与便利。代码如下(示例):父类类型对象名称......
  • 类和对象(上)
    1.类的定义1.1类定义格式class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成......
  • 06 php面向对象高级02
    7.继承PHP使用关键字extends来继承一个类,PHP不支持多继承,格式如下:classChildextendsParent{//代码部分}实例中Child_Site类继承了Site类,并扩展了功能<?php//子类扩展站点类别classChild_SiteextendsSite{var$category; functionsetC......
  • 在使用 PowerShell 与 Excel COM 对象交互时,Get-Member 命令通常用于查看对象的成员(方
    在使用PowerShell与ExcelCOM对象交互时,Get-Member命令通常用于查看对象的成员(方法、属性等)。不过,Excel的COM对象可能会出现一些成员在使用Get-Member时无法完全显示的情况,尤其是在显示属性或方法时没有完全列出所有可用的成员。为了解决这个问题,可以使用以下几种方法来......
  • 遍历数组和对象的方法都有哪些?
    在前端开发中,遍历数组和对象的方法有很多,以下是常用的几种,并分别针对数组和对象进行说明:数组遍历:for循环:最基本的循环方式,可以完全控制循环的起始、结束和步长。constarr=[1,2,3,4,5];for(leti=0;i<arr.length;i++){console.log(arr[i]);}for.......
  • 里氏替换原则:Java面向对象设计的基石
            在面向对象编程(OOP)中,继承是一个强大的工具,它允许我们创建新的类(子类)来复用和扩展现有类(父类)的功能。然而,继承也带来了复杂性,特别是在确保子类能够正确替换父类而不破坏程序行为方面。为了解决这个问题,里氏替换原则(LiskovSubstitutionPrinciple,LSP)应运而生。......