前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面向对象(2)

面向对象(2)

作者头像
Qwe7
发布2022-08-03 14:24:07
1780
发布2022-08-03 14:24:07
举报
文章被收录于专栏:网络收集网络收集

继承

类的继承

子类继承父类后,无需定义也可使用父类定义好的 public/protected 方法和属性。也可以进行扩展和方法的重写。

  • 父类的属性值不会被子类继承,但子类可以通过父类提供的方法得到父类的属性值。
  • 父类的 static 方法不会被子类继承,子类的 static 方法会隐藏父类的同名 static 方法。
  • 父类的构造方法不会被子类继承,子类必须在构造方法首行调用父类构造方法(先构造父类,再构造子类)
代码语言:javascript
复制
final public class Trunk extends Car{ 
    // 重定义属性(未公开无法继承)
    String brand;
    String description = "this is a trunk";
    // 扩展属性
    int goods;
    // 扩展方法              
    public void load(int num){
        this.goods += num;
    }
    // 子类构造方法
    public Trunk(String brand){    
        super(brand);        
        this.goods = 0;                          
    }
    // 重写方法
    @Override         
    public void go(String loc){
        super.go(loc);                            
        System.out.print(" with" + goods + "goods"); 
        this.goods = 0;
    }
}Copy to clipboardErrorCopied

Object 类是一切 java 类的父类。对于普通的 java 类,即便不声明也默认继承了 Object 类。


接口继承

和类的继承类似。但 Java 类只能单继承,而 Java 接口可以多继承。

代码语言:javascript
复制
interface Charge extends Move, Fight{  
    public abstract void kill(int num);
}Copy to clipboardErrorCopied

多态

继承多态

  • 重载(overload):定义多种同名方法,调用时根据传入参数判定调用哪种方法。
  • 重写(override):子类定义完全相同的方法覆盖父类。

重写是多态的前提,其允许父类引用指向子类对象(引用类型为父类,指向的实际对象类型为子类)。

Car mycar = new Trunk("Benz");

但不允许子类引用指向父类对象。

Trunk mycar = new Car("Benz");

如果两个类之间存在继承关系,可以进行强制类型转换。强制类型转换只能改变引用类型,实际指向对象类型不会发生变化。

Trunk newCar = (Trunk)mycar;

方法多态

  • 调用普通方法 子类同名方法会覆盖父类。执行方法根据实际对象类型来判定,即执行子类重写的方法。
  • 调用 static / private / final 以及构造方法 特殊方法不能被覆盖,不存在多态。执行方法会根据引用类型来判定,即执行父类方法。
  • 调用成员变量 父类属性值不会被子类继承,不存在多态。调用变量会根据引用类型来判定,即得到父类属性值。
代码语言:javascript
复制
Car myCar = new Trunk("Benz");

myCar.go("London");                    // (trunk) go to London with 0 goods
myCar.showNum();                       // (car) 1
System.out.print(myCar.description);   // (car) this is a car

Trunk newCar = (Trunk)mycar;           // 强制类型转换
System.out.print(newCar.description);  // (trunk) this is a trunkCopy to clipboardErrorCopied

反射机制

JAVA 是动态编译语言(运行时才确定类型),支持反射机制。在运行状态中

  • 对于任意一个类,都能够知道这个类的所有属性和方法;
  • 对于任意一个对象,都能够调用它的任意一个方法和属性。

通过反射机制能更好地支持多态,降低模块耦合,提高代码灵活度(根据传入类名不同,就能实例化出不同的对象)。

但是在性能上会有较大的损耗。

尽管在应用层面很少使用反射机制,但在设计基础框架的时候反射机制非常有用。

反射机制运用

类的相关信息保存在以下类中,通过特定方法获取其对象能够知道这个类的信息。

  • Class 类:类
  • Constructor 类:类的构造方法
  • Field 类:类的属性
  • Method 类:类的方法
代码语言:javascript
复制
public class Reflection {
    public static void main(String[] args) {

        /************************** 获取 Class 对象 **************************/

        // 第一种方式 返回对象的类 【已有对象,获取类无意义】
        Student stu = new Student();
        Class stuClass = stu.getClass();

        // 第二种方式 获取数据类型的静态 class 属性 【需要导入类包】
        Class stuClass = Student.class;

        // 第三种方式 返回路径下的类 【常用】
        Class stuClass = Class.forName("Reflection.Student");

        /************************** 获取 Class 信息 **************************/

        // 获取类名
        String name = stuClass.getName());   

        // 获取类的公有构造方法
        Constructor[] conArray = stuClass.getConstructors();
        // 获取类的全部构造方法
        Constructor[] conArray = stuClass.getDeclaredConstructors();
        // 获取类的指定构造方法(参数)
        Constructor con = stuClass.getConstructor(null);
        Constructor con = stuClass.getDeclaredConstructor(char.class);

        // 获取类的公有属性
        Field[] fieldArray = stuClass.getFields(); 
        // 获取类的全部属性
        Field[] fieldArray = stuClass.getDeclaredFields();
        // 获取类的指定属性(属性名)
        Field f = stuClass.getField("name");    

        // 获取类的公有方法
        Method[] methodArray = stuClass.getMethods(); 
        // 获取类的全部方法                
        Method[] methodArray = stuClass.getDeclaredMethods();
        // 获取类的指定方法(方法名+形参类型)                  
        Method m = stuClass.getMethod("main", String.class);   

        /************************** 在对象中使用 **************************/

        Object obj = con.newInstance();   // 调用公有无参构造方法创建对象
        f.set(obj, "X-man");              // 为对象的公有属性赋值
        m.invoke(obj, "X-man");           // 调用对象的公有方法

    }Copy to clipboardErrorCopied

泛型在编译时检查类型安全,编译过后泛型被擦除、实际类型才确定。反射是在编译期模拟 java 运行时的环境读取和调用程序,因此不能获得泛型的实际类型。但可以通过反射越过泛型检查:

在 String 泛型的集合中,你甚至可以添加一个 Integer 类型的值。

代码语言:javascript
复制
public class Demo {
    public static void main(String[] args) throws Exception{
        ArrayList<String> strList = new ArrayList<>();    
        Class listClass = strList.getClass(); 
        Method m = listClass.getMethod("add", Object.class);
        m.invoke(strList, 100);
    }
}

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 继承
    • 类的继承
      • 接口继承
      • 多态
        • 继承多态
          • 方法多态
            • 反射机制
              • 反射机制运用
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档