Java—面向对象

简介: Java—面向对象

面向对象


什么是面向对象

  • 面向过程:根据解决问题的过程,直接设计系统。如 C 语言。
  • 面向对象:将问题分解成多个对象,设计模块化、低耦合的系统。如 java 语言。
  • 特性:封装、继承、多态。
  • 优点:使系统更加灵活,易维护、易复用、易扩展。

封装

普通内部类

定义在类中的类,可以使用外部类所有属性和方法。普通内部类属于具体对象,因此不能声明 static 成员变量和方法。

成员内部类依附外部类而存在。也就是说,如果要创建普通内部类的对象,就必须首先存在外部类的对象。

public class Test {
    public static void main(String[] args)  {
        // 创建内部类
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();  
        inner.output();
    }
}
// 外部类 
class Outter {
    private int num = "10";
    // 内部类  
    class Inner {
        void output(){
            System.out.println(num);
        }
    }
}Copy to clipboardErrorCopied
复制代码

局部内部类

定义在一个方法或者一个作用域里的内部类。对局部内部类的访问仅限于方法内或者该作用域内,且局部内部类不能被访问权限所修饰。

public class Test {
    public static void main(String[] args)  {
        // 创建内部类
        Factory f = new Factory();
        Gun myrifle = f.getRifle();  
    }
}
class Factory {
    // 局部内部类
    public Gun getRifle(){
        class Rifle extends Gun {   
            int len = 60;
        }
        return new Rifle();
    }
}Copy to clipboardErrorCopied
复制代码

匿名内部类

匿名内部类不用定义名称,但必须继承一个父类或实现一个接口。由于没有类名,匿名内部类不能定义构造器。在创建匿名内部类的时候会立即创建它的实例。因此匿名内部类只能使用一次,通常用来简化代码编写。

最常用的情况就是在多线程的实现上,创建线程类传入参数需要继承 Thread 类或实现 Runnable 接口。

// 父类或接口
interface Person {
    public void eat();
}
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() { 
            // 定义匿名内部类并直接使用
            public void eat() {
                System.out.println("eat apple");
            }
        };
        p.eat();
    }
}Copy to clipboardErrorCopied
复制代码

JDK 1.8 中引入了 Lambda 表达式,你甚至连方法名都不需要写。

public class Demo {
    public static void main(String[] args) {
        Person p = new Person(() -> {
            System.out.println("eat apple");
        });
        p.eat();
    }
}Copy to clipboardErrorCopied
复制代码

局部内部类和匿名内部类都定义在方法中,如果调用方法中的其他局部变量,只能调用外部类的局部 final 变量。因为在多线程中,外部类方法中定义的变量 A 在方法执行完毕后生命周期就结束了,而此时 Thread 对象的生命周期很可能还没有结束。内部类方法中访问的变量 A 实际上是拷贝。这就必须限定变量为 final,否则改动将导致数据不一致。

public class Test {
    public void test(final int b) {
        final int a = 10;
        new Thread(){
            public void run() {
                System.out.println(a);
                System.out.println(b);
            };
        }.start();
    }
}Copy to clipboardErrorCopied
复制代码

静态内部类

静态内部类是不需要依赖于外部类,可以在不创建外部类对象的情况下创建内部类的对象。静态内部类不能使用外部类的非 static 成员变量或者方法。

public class Test {
    public static void main(String[] args)  {
        // 无需外部对象,直接创建内部类
        Outter.Inner inner = new Outter.Inner();
    }
}
class Outter {
    static class Inner {
        int data = 0;
    }
}Copy to clipboardErrorCopied
复制代码

继承

类的继承

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

  • 父类的属性值不会被子类继承,但子类可以通过父类提供的方法得到父类的属性值。
  • 父类的 static 方法不会被子类继承,子类的 static 方法会隐藏父类的同名 static 方法。
  • 父类的构造方法不会被子类继承,子类必须在构造方法首行调用父类构造方法(先构造父类,再构造子类)
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 接口可以多继承。

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 以及构造方法
    特殊方法不能被覆盖,不存在多态。执行方法会根据引用类型来判定,即执行父类方法。
  • 调用成员变量
    父类属性值不会被子类继承,不存在多态。调用变量会根据引用类型来判定,即得到父类属性值。
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 类:类的方法
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 类型的值。

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);
    }


作者:武师叔

链接:https://juejin.cn/post/7105726661550669837

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

目录
相关文章
|
20天前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
13 2
|
2月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
2月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
35 4
|
2月前
|
Java
接口和抽象类【Java面向对象知识回顾②】
本文讨论了Java中抽象类和接口的概念与区别。抽象类是不能被实例化的类,可以包含抽象和非抽象方法,常用作其他类的基类。接口是一种纯抽象类型,只包含抽象方法和常量,不能被实例化,且实现接口的类必须实现接口中定义的所有方法。文章还比较了抽象类和接口在实现方式、方法类型、成员变量、构造方法和访问修饰符等方面的不同,并探讨了它们的使用场景。
接口和抽象类【Java面向对象知识回顾②】
|
1月前
|
存储 Java 程序员
Java基础-面向对象
Java基础-面向对象
16 0
|
2月前
|
安全 Java Go
面向对象程序设计语言:Java
Java语言语法和C语言和C++语言很接近,很容易学习和使用,Java丢弃了C++中很少使用的、很难理解的、令人迷惑的特性,Java语言不使用指针,而是引用,并提供了自动分配和回收内存空间,使得程序员不必为内存管理而担忧
56 2
|
3月前
|
Java 数据处理 开发者
【Java基础面试十二】、说一说你对面向对象的理解
这篇文章阐述了面向对象是一种以类和对象为基础,通过封装、继承和多态等概念来模拟现实世界中的事物及其相互关系的程序设计方法,它强调以事物为中心进行思考和系统构造,与结构化程序设计相比,更符合人类的自然思维方式。
【Java基础面试十二】、说一说你对面向对象的理解
|
3月前
|
Java
【Java基础面试十三】、面向对象的三大特征是什么?
这篇文章介绍了面向对象程序设计的三大基本特征:封装、继承和多态,其中封装隐藏对象实现细节,继承实现软件复用,多态允许子类对象表现出不同的行为特征。
【Java基础面试十三】、面向对象的三大特征是什么?
|
2月前
|
Java 开发者
Java 面向对象
Java 是一种面向对象的编程语言,通过对象与类的概念组织代码和数据。面向对象编程的核心包括类、对象、继承、多态、封装和抽象。类是对象的蓝图,定义了属性和行为;对象则是类的实例。继承允许子类继承父类的属性和方法,增强代码复用性;多态则支持通过相同接口调用不同类型对象的行为,包括方法重载和重写。封装通过公共方法隐藏对象细节,提高安全性;抽象则对对象特征进行提炼,通过抽象类和接口实现。理解这些概念有助于设计高效、可维护的 Java 应用程序。
|
3月前
|
Java 开发者 C++