首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java:根据参数类型调用不同方法的最有效方式,这些方法都共享同一个超类

在Java中,根据参数类型调用不同方法的最有效方式通常涉及使用多态性。多态性允许一个接口或超类引用指向其子类的对象,并且可以根据实际的对象类型调用相应的方法。以下是一些实现这一目标的方式:

基础概念

  1. 多态性:允许一个接口或超类引用指向其子类的对象,并根据实际的对象类型调用相应的方法。
  2. 方法重写(Override):子类可以重写超类中的方法,以提供特定的实现。
  3. 类型检查和方法分派:通过instanceof关键字进行类型检查,然后进行类型转换并调用特定方法。

相关优势

  • 代码复用:通过继承和方法重写,可以避免重复代码。
  • 扩展性:添加新的子类时,不需要修改现有代码,只需添加新的实现。
  • 维护性:代码结构更清晰,易于理解和维护。

类型

  1. 编译时多态(静态分派):主要通过方法重载实现。
  2. 运行时多态(动态分派):主要通过方法重写和继承实现。

应用场景

  • 框架设计:如Spring框架中的依赖注入。
  • 游戏开发:不同类型的角色或物品有不同的行为。
  • UI组件:不同类型的按钮或控件有不同的响应逻辑。

示例代码

假设有一个超类Animal和两个子类DogCat,每个子类都有自己的makeSound方法。

代码语言:txt
复制
class Animal {
    void makeSound() {
        System.out.println("Some generic animal sound");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Woof!");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal;

        // 创建Dog对象并赋值给Animal引用
        myAnimal = new Dog();
        myAnimal.makeSound();  // 输出: Woof!

        // 创建Cat对象并赋值给Animal引用
        myAnimal = new Cat();
        myAnimal.makeSound();  // 输出: Meow!
    }
}

解决常见问题

问题:如果需要根据参数类型调用不同的方法,但又不希望使用instanceof和类型转换,该怎么办?

解决方案:使用访问者模式(Visitor Pattern)。访问者模式允许在不修改现有类层次结构的情况下定义新的操作。

代码语言:txt
复制
interface AnimalVisitor {
    void visit(Dog dog);
    void visit(Cat cat);
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Woof!");
    }

    void accept(AnimalVisitor visitor) {
        visitor.visit(this);
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow!");
    }

    void accept(AnimalVisitor visitor) {
        visitor.visit(this);
    }
}

class SoundMaker implements AnimalVisitor {
    @Override
    public void visit(Dog dog) {
        System.out.println("Making Dog sound");
    }

    @Override
    public void visit(Cat cat) {
        System.out.println("Making Cat sound");
    }
}

public class Main {
    public static void main(String[] args) {
        AnimalVisitor visitor = new SoundMaker();

        Dog dog = new Dog();
        dog.accept(visitor);  // 输出: Making Dog sound

        Cat cat = new Cat();
        cat.accept(visitor);  // 输出: Making Cat sound
    }
}

通过这种方式,可以在不破坏封装性的前提下,根据对象的具体类型执行不同的操作。

希望这些信息对你有所帮助!如果有更多具体问题,欢迎继续提问。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Java核心知识点整理大全11-笔记

如果都定义成abstract,那么每个模式也要去实现另一模 式下的接口。不同的自定义同步器争用共享资源的方式也不同。...JAVA 内部类 Java 类中不仅可以定义变量和方法,还可以定义类,这样定义在类内部的类就被称为内部类。根 据定义的方式不同,内部类分为静态内部类,成员内部类,局部内部类,匿名内部类四种。...泛型方法() 你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数 类型,编译器适当地处理每一个方法调用。...因为他们接受一个或多个参数, 这些类被称为参数化的类或参数化的类型。...类型擦除的基本过程也比较简单,首先是找到用来替换类型参数的具体类。这个具体类一般 是 Object。如果指定了类型参数的上界的话,则使用这个上界。把代码中的类型参数都替换 成具体的类。

11410

漫谈模式之享元模式

结构 享元模式的基本结构如下: 这里涉及到的参与者有如下几种: 抽象享元角色(Flyweight) 此角色是所有的具体享元的超类,为这些类规定出需要实现的公共接口。...TeaOrder参数也可以简化成一个int类型的tableNumber参数。 享元工厂 根据口味获取茶对象。...游戏客户端 Client端使用Factory来获取障碍物对象,然后使用障碍物对象的方法来绘制游戏场景。由于相同类型的障碍物共享相同的对象,因此可以有效地减少内存占用和对象创建。...原型模式和享元模式的区别 原型模式和享元模式都是为了提高系统性能和效率而设计的模式,但它们的应用场景和实现方式不同,需要根据具体情况进行选择。...内部状态是对象共享的部分,外部状态是对象不同的部分。通过将内部状态保存在共享池中,多个对象可以共享同一个内部状态,而将外部状态保存在对象的属性中,每个对象可以拥有自己的不同属性。

499140
  • Spring系列之bean的使用

    class属性定义了这个 Bean 的全限定类名(包名+类名)。Spring 能管理几乎所有的 Java 类。一般情况,这个 Java 类会有一个默认的构造函数,用set方法设置依赖的属性。...子类 Bean 会继承父类 Bean 的所有属性,子类 Bean 也可以覆盖父类 Bean 的属性。注意:子类 Bean 和父类 Bean 是同一个 Java 类。...二、实例化Bean的三种方式 1.使用构造器实例化Bean 这是最简单的方式,Spring IOC容器即能使用默认空构造器也能使用有参数构造器两种方式创建Bean。...同一个HTTP session共享一个Bean,不同HTTP session使用不同的Bean,该作用域仅适用于webApplicationContext环境。...request内有效,因此可以根据需要放心的更改所建实例的内部状态, 而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。

    62010

    Java漫谈-数组

    数组超类是Objcet,可以在数组上调用Object类的所有方法。 每个数组都有一个关联的Class对象,与具有相同组成类型的所有其他数组共享(§10.8)。...[] (3) java.io.Serializable >1 P[] 数组类型的超类型关系与超类关系不同: 根据上面(即§4.10.3),Integer[]的直接超类型是Number[]。...多维数组的clone很浅,也就是说它只创建一个新数组。子阵列是共享的。 所有成员都继承自Object类;唯一没有继承的Object方法是它的clone方法。...: 不必为需要应用的每种不同的类型都使用一个参数去实例化这个类,并且可以将其自定义为静态的。...一般而言,会发现泛型在类或方法的边界处很有效,而在类或方法的内部,擦除通常会使泛型变得不适用。如,不能创建泛型数组。

    1.2K10

    Java语言中的面向对象特性总结

    其中参数的类型可以是简单数据类型,也可以是复合数据类型(又称引用数据类型)。    对于简单数据类型来说,java实现的是值传递,方法接收参数的值,但不能改变这些参数的值。...5.方法重载   方法重载是指多个方法享有相同的名字,但是这些方法的参数必须不同,或者是参数的个数不同,或者是参数类型不同。返回类型不能用来区分重载的方法。    ...参数类型的区分度一定要足够,例如不能是同一简单类型的参数,如int与long。编译器会根据参数的个数和类型来决定当前所使用的方法。  6. 构造方法    ◇ 构造方法是一个特殊的方法。...1) 编译时多态    在编译阶段,具体调用哪个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。    ...1) 实例变量和类变量    每个对象的实例变量都分配内存,通过该对象来访问这些实例变量,不同的实例变量是不同的。

    44520

    JVM内存模型

    池中的数据项象数组项一样,是通过索引访问的。 每个类的这些元数据,无论是在构建这个类的实例还是调用这个类某个对象的方法,都会访问方法区的这些元数据。...类变量被类的所有实例共享,即使没有类实例时你也可以访问它。这些变量只与类相关,所以在方法区中,它们成为类数据在逻辑上的一部分。...例如,假如同时有两个线程都企图访问方法区中的同一个类,而这个类还没有被装入JVM,那么只允许一个线程去装载它,而其它线程必须等待 2、方法区的大小不必是固定的,JVM可根据应用需要动态调整。...另外,在Java 堆中还必须包含能查找到此对象类型数据(如对象类型、父类、实现的接口、方法等)的地址信息,这些类型数据则存储在方法区中。...由于reference 类型在Java 虚拟机规范里面只规定了一个指向对象的引用,并没有定义这个引用应该通过哪种方式去定位,以及访问到Java 堆中的对象的具体位置,因此不同虚拟机实现的对象访问方式会有所不同

    55140

    《Effective Java》——读后总结

    [1240] 1、静态工厂方法代替构造器 静态工厂方法有名称,能确切地描述正被返回的对象。 不必每次调用都创建一个新的对象。 可以返回原返回类型的任何子类对象。...对于所有对象都通用的方法 5、覆盖 equals 如果类具有自己特有的"逻辑相等",但超类还没有覆盖 equals 以实现期望的行为。...保护性拷贝是在检查参数的有效性之前进行的,并且有效性检查是针对拷贝之后的对象。 17、 慎用重载 重载方法的选择是静态的,选择工作时在编译时进行,完全基于参数的编译时类型。...不要导出俩个具有相同参数数目的重载方法,如果参数数目相同,则至少有一个对应的参数在俩个重载方法中具有根本不同的类型,否则就应该保证,当传递同样的参数时,所有的重载方法的行为必须一致。...26、同步访问 同步可以阻止一个线程看到对象处于不一致的状态之中,还能保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护的之前所有的修改效果。

    1.5K10

    Java基础教程(8)-Java中的面向对象和类(二)

    default : 表明该成员变量或者方法只有自己和其位于同一个包的内可见,其他包内的类不能访问,即便是它的子类继承通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”...只有当子类真正是超类的子类型时,才适合用继承多态所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。...这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用;最常见的多态就是将子类传入父类参数中,运行时调用父类方法时通过传入的子类决定具体的内部结构或行为...(Overriding)重写指的是在 Java 的子类与父类中有两个名称、参数列表都相同的方法的情况。...2、重载遵循所谓“编译期绑定”,即在编译时根据参数变量的类型判断应该调用哪个方法。3、重写遵循所谓“运行期绑定”,即在运行的时候,根据引用变量所指向的实际对象的类型来调用方法。

    9710

    独特视角解读JVM内存模型

    当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。 由于java虚拟机采取这种方式进行类的加载,所以被装载的类默认情况下只能看到同一个类加载器装载的类。...在java虚拟机中,在同一个命名空间内的类可以直接进行交互,而不同的命名空间中的类甚至不能察觉到彼此的存在。...实例方法数据"的指针,方法表指向的实例方法数据包括以下信息: 此方法的操作数栈和局部变量区的大小 此方法的字节码 异常表 这些信息足够虚拟机去调用一个方法,方法表中包含有方法指针,该指针指向当前类或者其超类什么的方法数据...对于一个实例方法调用而言,参数this总是作为隐式参数传入的,它用来表示调用该方法的对象本身。...对于面向对象语言来说,内嵌就变得复杂了,因为动态方法派发意味着一个函数调用可能有多个函数实现(方法),换句话说,虚拟机运行时根据方法调用的对象类,可能会有很多不同的方法实现可供选择。

    40120

    jdk和jvm区别_java中集合和数组的区别

    方法区存放的信息包括:A 类的基本信息: 1.每个类的全限定名 2.每个类的直接超类的全限定名(可约束类型转换) 3.该类是类还是接口 4.该类型的访问修饰符 5.直接超接口的全限定名的有序列表...3.方法信息:类中声明的每一个方法的信息,包括方法名、返回值类型、参数类型、修饰符、异常、方法的字节码。...4.静态变量:就是类变量,类的所有实例都共享,我们只需知道,在方法区有个静态区,静态区专门存放静态变量和静态块。 5.到类classloader的引用:到该类的类装载器的引用。...而jvm必须以某种方式把Class的这个实例和存储在方法区中的类型数据联系起来。...根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。

    30820

    Java虚拟机体系结构

    JAVA虚拟机的体系结构 下图是JAVA虚拟机的结构图,每个Java虚拟机都有一个类装载子系统,它根据给定的全限定名来装入类型(类或接口)。...对于每个装载的类型,虚拟机都会在方法区中存储以下类型信息:   ● 这个类型的全限定名   ● 这个类型的直接超类的全限定名(除非这个类型是java.lang.Object,它没有超类)   ● 这个类型是类类型还是接口类型...另一条指令将用这个引用调用Lava对象引用的flow()方法。 堆 Java程序在运行时创建的所有类实例或数组都放在同一个堆中。而一个JAVA虚拟机实例中只存在一个堆空间,因此所有线程都将共享这个堆。...但是同一个Java程序的多个线程却共享着同一个堆空间,在这种情况下,就得考虑多线程访问对象(堆数据)的同步问题了。...传递给该函数的参数以某个确定的顺序压入栈,它的返回值也以确定的方式传回调用者。同样,这就是虚拟机实现中本地方法栈的行为。

    1.8K10

    Java知识面试题复习(三)Java面向对象

    运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事: 方法重写(子类继承父类并重写父类中已有的或抽象的方法); 对象造型(用父类型引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为...对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法...相同点 接口和抽象类都不能实例化 都位于继承的顶端,用于被其他实现或继承 都包含抽象方法,其子类都必须覆写这些抽象方法 不同点 现在,我们可以为接口提供默认实现的方法了,并且不用强制子类来实现它...重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分 重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类...引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

    38230

    【Java学习笔记之十六】浅谈Java中的继承与多态

    表示父类和子类的术语:父类和子类、超类和子类、基类和派生类,他们表示的是同一个意思。 2、  为什么需要继承?什么时候应该继承? 使用继承可以有效实现代码复用,避免重复代码的出现。...如果在子类中定义的一个方法,其名称、返回类型及参数列表正好与父类中某个方法的名称、返回类型及参数列表相匹配,那么可以说,子类的方法重写了父类的方法。 方法重写在不同类,是实现多态的必要条件。...调用这个方法时,实例化不同的子类对象(new 一个对象)。 更具体的说: (1)、子类重写父类的方法。使子类具有不同的方法实现。 (2)、把父类类型作为参数类型,该父类及其子类对象作为参数转入。...(3)、运行时,根据实际创建的对象类型动态决定使用那个方法。 在运行时,java虚拟机会根据实际创建的对象类型决定使用那个方法。一般将这称为动态绑定。   ...当把子类作为参数传递给这个方法时,java虚拟机会根据实际创建的对象类型,调用子类中相应的方法(存在方法重写时)。

    1.1K70

    《Java核心技术 卷I:基础知识》读书笔记

    一定要对数据初始化 不要在类中使用过多的基本类型(便于理解) 不是所有的域都需要独立的域访问器和域更改器。 将职责过多的类进行分解 类名和方法名要能体现它们的职责。...与之对应,调用的方法依赖于隐式参数(this)的实际类型,这种方式称为动态绑定。 5.1.4 阻止继承 不允许扩展的类称为final类 类中特定方法也可以声明为final,这样子类就不能覆盖这个方法。...最关键的就是java.lang.reflect.Array.newInstance静态方法,它能够构造新数组,调用它时必须提供数组的元素类型和数组的长度。...一些值得注意的点 调用时可以省略泛型,编译器可以根据参数自动推断。...13.2.8 映射表 map映射表,根据某些键的信息来查找与之对应的元素。HashMap是非常常用的工具。 与散列表不同,映射表中键是唯一的,同一个键中后赋的值会直接覆盖先赋的值。

    59520

    JAVA面试题全集(上)

    抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。 - 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。...- 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。...对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。...答:Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class...重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问

    50910

    JavaScript面向对象程序设计之继承(一)

    name, 又共享了 公有的方法 sayName(),这样就实现了类似于强类型语言中类的概念。...这也很好理解,因为两个实例都继承自SuperType的同一个实例构成的原型,所以他们共享了超类型构造函数中的element属性,因此,理所应当的,前一个实例对element元素所作的更改会体现在后一个实例上...这是一个令人头疼的问题。 原型链式继承的另一个问题是,子类型的构造函数中,无法给超类型传递参数。这也局限了这种方式在实际开发中的应用。 2....虽然都实现了相同的功能,但两个方法并不是同一个方法。还是上面说的,借用构造函数仅仅只是复制了一份超类型中的属性和方法,这并不是复用,借用构造函数无法实现公共方法的复用。...,根据打印结果可以看到,组合模式既可以复用超类型的公用方法,子类型实例中又可以保有各自的私有属性。

    36210

    31道Java核心面试题,一次性打包送给你

    堆(Heap),在 JVM 中,堆是可供各条线程共享的运行时内存区域,也是供所有类实例和数据对象分配内存的区域。 方法区(Method area),在 JVM 中,被加载类型的信息都保存在方法区中。...,但方法参数的个数不同,另外也不涉及到继承,两个方法在同一个类中。...在编译期间,编译器就知道这两个 read() 方法时不同的,因为它们的方法签名(=方法名称+方法参数)不同。...简单的来总结一下: 1)编译器无法决定调用哪个重写的方法,因为只从变量的类型上是无法做出判断的,要在运行时才能决定;但编译器可以明确地知道该调用哪个重载的方法,因为引用类型是确定的,参数个数决定了该调用哪个方法...static 关键字可以用来修饰类变量,使其具有全局性,即所有对象将共享同一个变量。 static 关键字可以用来修饰方法,该方法称为静态方法,只可以访问类的静态变量,并且只能调用类的静态方法。

    75210

    知识点总结:Java核心技术(卷1)

    “==”运算符能够用来确定两个字符串是否放在同一个位置。如果两个字符串放在同一个位置,它们必然相等。完全有可能将相同内容的字符串放在不同的位置上。 使用equals 方法比较两个字符串是否相等。...this的用途 1、引用隐式参数; 2、调用该类的其他的构造器; super的用途 1、调用超类的方法; 2、调用超类的构造器; 子类和超类 子类 子类构造器 使用super...调用构造器的语句必须是子类构造器的第一条语句; 如果子类构造器没有显式调用超类构造器,将自动地调用该超类的默认构造器(没有参数的构造器) 如果子类构造器没有显式的调用超类构造器,超类又没有不带参数的构造器...,同名而且有相同参数类型的默认方法会被忽略; 子主题 3 2)接口冲突; 如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型(不论是否为默认方法)相同的方法,必须覆盖这个方法来解决冲突...无论何时定义一个泛型类型,都自动提供了一个响应的原始类型。原始类型的名字就是删去类型参数后的泛型类型名。

    34430

    Java-值传递和值引用

    1.形参和实参的区别? 形参:方法被调用时需要传递进来的参数,只有在被调用时才分配内存单元,在调用结束时,就会释放出所分配的内存单元。形参只能在函数内部才有效....所以,数据在内存中的存储,是根据数据类型来划定存储形式和存储位置的. 我们都知道数据类型分为基本数据类型和引用数据类型: 基本类型:编程语言中内置的最小粒度的数据类型。...3.方法区 方法区是一块所有线程共享的内存逻辑区域,在JVM中只有一个方法区,用来存储一些线程可共享的内容,它是线程安全的,多个线程同时访问方法区中同一个内容时,只能有一个线程装载该数据,其它线程只能等待...方法区可存储的内容有:类的全路径名、类的直接超类的权全限定名、类的访问修饰符、类的类型(类或接口)、类的直接接口全限定名的有序列表、常量池(字段,方法信息,静态变量,类型引用(class))等。...因此可知:基本数据类型的成员变量名和值都存储于堆中,其生命周期和对象的是一致的,在JVM中只有一个堆,因此,堆是被所有线程共享的。

    1.7K30

    Spring常见面试题总结(超详细)

    DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部依赖。...(2)最直观的表达就是,以前创建对象的主动权和时机都是由自己把控的,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象...Spring基于xml注入bean的几种方式 Spring基于xml注入bean的几种方式: set()方法注入; 构造器注入:通过index设置参数的位置;通过type设置参数类型; 静态工厂注入...,针对不同的资源文件,实现了不同方式的资源获取策略 (4)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术 (5)模板方法:可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中...降低Java EE API的使用难度   Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE

    90821
    领券