首页 > 编程语言 >再探Java为面试赋能(二)Java基础知识(二)反射机制、Lambda表达式、多态

再探Java为面试赋能(二)Java基础知识(二)反射机制、Lambda表达式、多态

时间:2024-04-09 14:30:21浏览次数:20  
标签:... Java Food 重写 多态 public 方法 Class 赋能

文章目录

前言

往期精选:

再探Java为面试赋能(一)Java基础知识(一)变量初始化顺序、构造方法、clone方法

1.4 反射机制

Java语言的反射机制,是指动态获取类或对象的属性以及方法,从而完成调用功能的一种机制。它主要实现了以下功能:

  • 获取类的访问修饰符、属性、方法以及父类信息。
  • 在运行时根据类名创建对象,还可以调用对象的任意方法。
  • 生成动态代理。

1.4.1 Class对象的获取

在反射机制中,Class类是一个非常重要的类,获取Class对象主要有3种方法:

  • 1)通过className.class获取:
public class Food {

    static {
        System.out.println("Food类的静态代码块执行了...");
    }

    {
        System.out.println("Food类的非静态代码块执行了...");
    }

    public static void main(String[] args) {
        Class<Food> aClass = Food.class;
        System.out.println("className = " + aClass.getName());
    }
}

程序运行结果:

Food类的静态代码块执行了...
className = test03.Food
  • 2)通过Class.forName()获取:
public class Food {

    static {
        System.out.println("Food类的静态代码块执行了...");
    }

    {
        System.out.println("Food类的非静态代码块执行了...");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> food = Class.forName("test03.Food");
        System.out.println("className = " + food.getName());
    }
}

程序运行结果:

Food类的静态代码块执行了...
className = test03.Food
  • 3)通过Object.getClass()获取:
public class Food {

    static {
        System.out.println("Food类的静态代码块执行了...");
    }

    {
        System.out.println("Food类的非静态代码块执行了...");
    }

    public static void main(String[] args) {
        Class<? extends Food> aClass = new Food().getClass();
        System.out.println("className = " + aClass.getName());
    }
}

程序运行结果:

Food类的静态代码块执行了...
Food类的非静态代码块执行了...
className = test03.Food

如上面的例子所示,三种方式都可以获得类的Class对象,但也有一些区别:

  • 方法 1)2)执行静态代码块,但不执行非静态代码块;
  • 方法 3)由于创建了对象,因此会执行静态代码块和非静态代码块。

1.4.2 Class类的方法

Class类提供了非常多的方法,常用的有三类:

  • 1)获取类的构造方法

构造方法的封装类为Constructor。

源码:java.lang.Class

// 返回类的所有的public构造方法
public Constructor<?>[] getConstructors()
// 返回类的指定参数的public构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
// 返回类的所有构造方法
public Constructor<?>[] getDeclaredConstructors()
// 返回类的指定参数的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
  • 2)获取类的成员变量的方法

成员变量的封装类为Field。

源码:java.lang.Class

// 返回类的所有public成员变量
public Field[] getFields()
// 返回类的指定名称的public成员变量
public Field getField(String name)
// 返回类的所有成员变量
public Field[] getDeclaredFields()
// 返回类的指定名称的成员变量
public Field getDeclaredField(String name)
  • 3)获取类的方法

方法的封装类为Method。

源码:java.lang.Class

// 返回类的所有public方法
public Method[] getMethods()
// 返回类的指定名称和参数的public方法
public Method getMethod(String name, Class<?>... parameterTypes)
// 返回类的所有方法
public Method[] getDeclaredMethods()
// 返回类的指定名称和参数的方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

1.4.3 通过反射机制修改只读类的属性

有如下代码:

public class ReadOnlyClass {
    
    private Integer age = 20;

    public Integer getAge() {
        return age;
    }
}

在这个类中,age属性被修饰为private,且只提供了getter方法,而没有提供setter方法,因此这个类型是一个只读的类,无法通过常规方法修改age属性。

但通过Java的反射机制就可以修改age属性。例如:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    ReadOnlyClass roc = new ReadOnlyClass();
    System.out.println("修改前age = " + roc.getAge());

    Class<ReadOnlyClass> aClass = ReadOnlyClass.class;
    Field field = aClass.getDeclaredField("age");
    field.setAccessible(true);
    // 修改roc对象的age属性
    field.set(roc, 30);
    System.out.println("修改后age = " + roc.getAge());
}

执行结果:

修改前age = 20
修改后age = 30

1.5 Lambda表达式

简单来说,Lambda表达式就是对匿名内部类的简写。它的基本语法是:

<函数式接口> <变量名> = (参数1, 参数2, ...) -> {
    // 方法体
}

1.5.1 函数式接口

函数式接口就是一个有且仅有一个抽象方法的接口。

例如Runnable接口就是一个函数式接口:

源码:java.lang.Runnable

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

可见,Runnable接口中只包含一个抽象的run()方法,并且在接口上标注了一个@FuncationInterface注解,此注解就是 Java 8 新增的注解,用来标识一个函数式接口。

想要自定义一个函数式接口也非常简单,只需要在接口中定义一个抽象方法,然后在接口上标记@FunctionalInterface注解。

当然,该注解也可以不标记,只是说标记了该注解,编辑器会自动检测自定义的函数式接口是否有问题。例如:

1.5.2 Lambda表达式的使用

下面是一个自定义的函数式接口,定义了一个有参数有返回值的sum()方法:

@FunctionalInterface
public interface MyInterface {

    public abstract int sum(int a, int b);
}

使用Lambda表达式调用该方法:

public static void main(String[] args) {
    // 使用匿名内部类方式
    MyInterface myInterface = new MyInterface() {
        @Override
        public int sum(int a, int b) {
            return a+b;
        }
    };
    int sum = myInterface.sum(5, 10);
    System.out.println("匿名内部类方式 sum = " + sum);

    // 使用Lambda表达式
    MyInterface myi = (a, b) -> a+b;
    int sum1 = myi.sum(2, 8);
    System.out.println("Lambda表达式方式 sum1 = " + sum1);
}

执行结果:

匿名内部类方式 sum = 15
Lambda表达式方式 sum1 = 15

可见,使用Lambda表达式后,代码变得更加简介。

Lambda表达式还有更多编写规则如下:

  • 1)参数只需要参数名称,不需要参数类型,编译器会自动推断类型。如示例中:(a, b)
  • 2)如果参数只有一个,可以省略小括号(),没有参数或者参数多于一个,不能省略小括号。
  • 3)方法体只有一行代码时,可以省略中括号{}
  • 4)方法体只有一行代码时,且有返回值时,可以省略return关键字。如示例中:-> a+b

1.6 多态

1.6.1 多态的概念

多态是面向对象编程中的一个重要概念,它允许不同类型的对象对同一方法进行不同的实现。

具体来说,多态是指通过父类的引用变量来指向子类的对象,从而实现对不同对象的统一操作。

例如,猫和狗都是动物,都有“吃”这个共同行为,具体表现在狗身上可能是啃骨头,表现在猫身上可能是吃猫粮。这就是多态的表现,即同一件事情,发生在不同的对象身上,就会产生不同的结果。

1.6.2 多态的实现条件

在Java中,要实现多态性,就必须满足以下条件:

  • 1)继承关系
  • 2)方法重写
  • 3)父类引用指向子类对象

例如,首先定义一个父类Animal,该类有一个eat()方法:

public class Animal {

    public void eat() {
        System.out.println("动物吃东西...");
    }
}

再定义两个子类Dog和Cat,均继承父类Animal,并重写其eat()方法:

public class Dog extends Animal {

    // 1.继承关系
    // 2.方法重写
    @Override
    public void eat() {
        System.out.println("狗啃骨头...");
    }
}
public class Cat extends Animal {

    // 1.继承关系
    // 2.方法重写
    @Override
    public void eat() {
        System.out.println("猫吃猫粮...");
    }
}

最后编写测试方法:

public class Main {

    public static void main(String[] args) {
        // 3.父类引用指向子类对象
        Animal dog = new Dog();
        Animal cat = new Cat();

        dog.eat();
        cat.eat();
    }
}

执行结果:

狗啃骨头...
猫吃猫粮...

1.6.3 重载(Overload)和重写(Override)

Java中多态的实现条件之一是方法重写,是指子类重新定义和实现从父类继承而来的方法,以改变方法的行为,提供自己特定的实现。

方法重写必须遵循一些规则:

  • 1)子类重写方法的名称、参数列表(包括数量、类型、顺序)和返回值类型都必须与父类中被重写的方法相同。
  • 2)重写方法的访问修饰符的权限不能低于父类方法的权限。例如,父类方法被public修饰,则子类中重写方法就不能声明为protected
  • 3)重写方法不能抛出比父类方法更多或更宽泛的异常,重写方法可以抛出相同的异常或更具体的异常,或者不抛出异常。
  • 4)重写方法可以通过super()函数调用父类方法的逻辑。

重载是指在一个类中定义了多个同名的方法。 它也必须遵循一些规则:

  • 1)重载的方法必须定义在一个类中,它们的名称必须相同。
  • 2)重载的方法的参数列表必须不同,可以通过参数的个数、类型、顺序的不同来进行区分。
  • 3)重载的方法的返回值类型可以相同也可以不同。

总结一下,重载和重写的区别:

  • 1)定义位置。重载方法定义在同一个类中,而重写方法定义在父类和子类之间。
  • 2)方法签名。重载方法具有相同的名称,但方法签名(参数类型、个数或顺序)不同,而重写方法具有相同的名称和方法签名。
  • 3)调用时机。重载方法是根据方法签名的不同进行静态绑定,在编译时就确定,而重写方法是根据对象的实际类型进行动态绑定,要在运行时确定。

本节完,更多内容请查阅分类专栏:再探Java为面试赋能

感兴趣的读者还可以查阅我的另外几个专栏:

标签:...,Java,Food,重写,多态,public,方法,Class,赋能
From: https://blog.csdn.net/weixin_42739799/article/details/137479535

相关文章

  • java计算机毕业设计医院挂号系统小程序【附源码+远程部署+程序+mysql】
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着信息技术的飞速发展,传统的医院挂号方式已逐渐不能满足现代社会对医疗服务效率和质量的要求。长期以来,患者在医院现场排队挂号不仅耗时耗力,还可能因等......
  • 数据中心赋能企业数字化转型
    中国联通新一代全球智·云数据中心:构筑智能互联时代的全球数据中枢中国联通新一代全球智·云数据中心,作为数字化时代前沿科技与创新服务的结晶,以其独特地理优势、全球通达网络、云网安融合一体的架构,以及智慧安全运营体系,为全球用户构建起一座集高效、安全、智能于一体的现代化数......
  • 8.Java常用类
    文章目录1.String1.1String的特性1.2String对象创建1.2.1字符串的特性1.2.2intern()1.2.3String使用细节1.3String常用方法1.4String类型转换1.4.1String与包装类1.4.2String与char[]数组1.4.3String与Byte[]数组2.StringBuffer与StringBuilder2.1字符串......
  • java计算机毕业设计基于微信小程序的线上奶茶店【附源码+远程部署+程序+mysql】
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着移动互联网技术的飞速发展,微信作为中国最流行的社交应用之一,其小程序功能也日渐成为用户日常生活的一部分。微信小程序以其无需下载安装、使用方便的......
  • 【附源码】JAVA计算机毕业设计校内互助学习(源码+mysql+文档)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义标题:设计校内互助学习app3sy9t在当今教育领域,随着信息技术的迅速发展和智能手机的普及,数字化学习工具已成为辅助教学的重要手段。然而,现有的学习应用多数集中于......
  • 【附源码】JAVA计算机毕业设计校园二手拍卖网(源码+mysql+文档)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:在校园内,学生们经常面临着教材更新换代、生活用品升级以及兴趣爱好转变等情况,这些变化往往导致许多物品失去了原有的使用价值,而被闲置或丢弃。同时,新入......
  • 【附源码】JAVA计算机毕业设计校医务系统(源码+mysql+文档)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:在当今社会,随着科技的迅猛发展和人们健康意识的不断提升,医疗信息化已成为提高医疗服务质量与效率的重要手段。特别是在校园环境中,学生作为特殊群体,其健......
  • 【附源码】JAVA计算机毕业设计校园二手物品交易网站(源码+mysql+文档)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着互联网技术的迅猛发展和数字化生活方式的普及,线上交易平台已经成为人们生活中不可或缺的一部分。特别是在校园内部,学生们在学习生涯中积累了大量书......
  • 【附源码】JAVA计算机毕业设计校园安保巡查系统(源码+mysql+文档)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义标题:校园安保巡查系统373qv的设计与实现在教育场所,安全始终是放在首位的重要议题。随着信息技术的发展,传统的校园安保措施已逐渐不能满足日益增长的安全需求。因......
  • 【附源码】JAVA计算机毕业设计校园活动管理系统(源码+mysql+文档)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着信息技术的不断发展和教育现代化的深入推进,校园活动作为丰富学生课余生活、提升综合素质的重要途径,其管理方式也亟需与时俱进。传统的校园活动管理......