java 面向对象编程

目录

继承

多态

动态绑定

接口

接口多重继承 

抽象类

异常处理 

捕获异常

抛出异常

转型

泛型

泛型方法

内部类


继承

有两种方法使子类和父类不同:1.拓展(extends),在子类添加新方法,这方法并不是基类接口的一部分。2.覆盖(overriding),子类使用相同接口,但是创建了该方法的新定义。继承原则如下:

  1. 能够继承父类的public和protected成员变量和方法;不能够继承父类的private成员变量方法;
  2. 对于父类的包访问权限成员变量和方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;
  3. 对于子类可以继承的父类成员变量和方法,如果在子类中出现了同名称的成员变量,则会发生隐藏,即子类的成员变量会屏蔽掉父类的同名成员变量。如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员变量和方法,需要使用super关键字来进行引用。注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的。

注意:当创建一个导出类的对象时,该对象包含了一个基类的子对象一起被创建,子对象包装在导出类对象内部,构建过程是从基类“向外”扩散的,所以基类在导出类构造器访问它之前,就已经完成初始化。

class Cleanser {
    private String s = "Cleanser";
    public void append(String a) { s += a; }
    public void dilute() { append(" dilute()"); }
    public void apply() { append(" apply()"); }
    public void scrub() { append(" scrub()"); }
    public String toString() { return s; }
    public static void main(String[] args) {
        Cleanser x = new Cleanser();
        x.dilute(); x.apply(); x.scrub();
        System.out.print(x);
    }
}

public class Detergent extends Cleanser {
    public void scrub() {
        append(" Detergent.scrub()");
        super.scrub(); 
    }
    public void foam() { append(" foam()"); }
    public static void main(String[] args) {
        Detergent x = new Detergent();
        x.dilute();
        x.apply();
        x.scrub();
        x.foam();
        System.out.print(x);
        System.out.print("Testing base class:");
        Cleanser.main(args);
    }
}
/*Cleanser dilute() apply() Detergent.scrub() scrub() foam()Testing base class:
Cleanser dilute() apply() scrub()*/

多态

对于父类CreditCard和子类PredatoryCreditCard我们有下面的对象赋值语法。我们说变量card是多态的;它可能是多种形式中的一种,这取决于它所引用对象的特定类。因为变量card是用CreditCard,类型声明的,可以调用CreditCard.makepayment和CreditCard.charge,但是调用PredatoryCreditCard.processMonth会报告编译错误,因为信用卡不能保证有这种行为。

CreditCard card = new PredatoryCreditCard(...);

在面对对象设计中语言中,多态是继数据抽象和继承后的第三种基本特性。多态分两种:

  1. 编译时多态:方法重载。 
  2. 运行时多态:JAVA运行时系统根据调用该方法的实例的类型来决定选择调用哪个方法则被称为运行时多态。

运行时多态存在的三个必要条件:要有继承(包括接口的实现);要有重写;父类引用指向子类对象

动态绑定

将一个方法调用同一个类关联起来被称作绑定。若在程序执行前进行绑定,叫做前向绑定。C语言只有一种方法调用,即前向绑定。Java中除了static和final方法之外,其他所有的方法都是后期绑定。后期绑定,它的含义是在运行时根据对象的类型进行绑定,也叫动态绑定。也就是说,编译器一直不知道对象的类型,但是方法调用机制能够找到正确的方法体,并加以调用。

有一个基类Shape以及多个导出类—Circle、Square、Triangle等,经过向上转型。通过继承,Circle就是一种Shape,当你调用一个他们共有的方法(它已经在导出类被覆盖):由于后期绑定(多态),最后还是正确调用了Cricle.draw()方法。

Shape s = new Circle();    //Shape和Circle都有draw()方法
s.draw();

接口

接口是为了解决java不能多类继承的缺陷。接口的唯一目的是被一个或多个类实现。

interface关键词产生一个完全抽象的类,允许确定方法名、参数列表和返回类型,但是没有任何方法体。创建一个接口,需要用interface关键词代替class关键词。属性域必须是public final static。让一个类遵循某一个或几个已创建的特定接口,需要使用implements关键字,一旦实现某个接口,实现的类就变成一个普通类,就可以按常规方式扩展继承。 

public class Test {
    public void tune(Instrument instrument) {
        instrument.Play();
    }
    public void tune(Instrument[] instruments) {
        for (int i = 0; i < instruments.length; i++) {
            tune(instruments[i]);
        }     }
    public static void main(String[] args) {
        Test test = new Test();
        // Instrument instrument = new Instrument();//error  
        Instrument wind = new Wind();
        Instrument bass = new Bass();
        Instrument[] instruments = { wind, bass };
        test.tune(instruments);
        System.out.println(Instrument.id);// id是static  
    }  }
interface Instrument {
    // private int id=0;//error  
    // private void Play();//error  
    int id = 0;
    void Play();
}
class Wind implements Instrument {
    @Override
    public void Play() {
        // id=2;//The final field Instrument.id cannot be assigned  
        System.out.println(id);
        System.out.println("wind play");
    }  }
class Bass implements Instrument {
    @Override
    public void Play() {
        System.out.println("bass play");
    }
}  
  1. 接口是不可以new 的。
  2. 当类实现接口时,它必须实现接口中声明的所有方法
  3. 通过向上转型,以Instrument为类型定义的wind和bass,也可以调用play方法,而且运行时自动识别应该绑定那个play方法。
  4. 由于wind和bass必须重写play,因此play一定是public,因为wind和bass不是继承Instrument。
  5. 我们通过打印Instrument里面的id,知道id一定是static,因为可以直接使用Instrument调用,而不需要new。
  6. 通过在实现类wind里面修改id,就可以看到他的提示,提示id是final的。 
Java内置接口

 

接口

方法

比较

java.lang.Comparable

compareTo()

Java.util.comparator

compare()

迭代

Java.lang.Iterable

iterator()

hasNext()

Java.util.Iterator

next()

remove()

接口多重继承 

接口没有任何具体实现,也就没有与接口有关的存储,也就无法阻止多个接口组合。组合多个类的接口的行为被称作多重继承

public class Test {
    public static void testSwim(CanSwim canSwim) {
        canSwim.swim();
    }
    public static void testEat(CanEat canEat) {
        canEat.eat();
    }
    public static void testRun(CanRun canRun) {
        canRun.run();
    }
    public static void main(String[] args) {
        Person person = new Person();
        testSwim(person);//向上转型为CanSwim  
        testEat(person);//向上转型为CanEat  
        testRun(person);//向上转型为CanRun  
        Fish fish = new Fish();
        testSwim(fish);//  
        // testEat(fish);//error,因为没有实现接口,不能向上转型  
        // testRun(fish);//error,因为没有实现接口,不能向上转型  
    }  }
interface CanRun {
    void run();
}
interface CanSwim {
    void swim();
}
interface CanEat {
    void eat();
}
class Person implements CanEat, CanRun, CanSwim {
    @Override
    public void swim() {
        System.out.println("i can swim");
    }
    @Override
    public void run() {
        System.out.println("i can run");
    }
    @Override
    public void eat() {
        System.out.println("i can eat");
    } }
class Fish implements CanSwim {
    @Override
    public void swim() {
        System.out.println("i can swim");
    }
} 

抽象类

在Java中,抽象类在传统类和接口类之间起到一定的作用。与接口一样,抽象类可以为一个或多个方法定义签名,而不提供这些方法体的实现;这种方法称为抽象方法。

抽象类和接口的对比
参数抽象类接口
默认的方法实现抽象类中可以有一个或多个抽象方法,也就是说抽象类是包含一个或多个抽象方法的类接口中的方法必须都是抽象方法
实现子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。子类使用关键字implements来实现接口。被强制需要提供接口中所有声明的方法的实现
构造器抽象类可以有构造器接口不能有构造器
与正常Java类的区别除了你不能实例化抽象类之外,它和普通Java类没有任何区别接口是完全不同的类型
访问修饰符抽象方法可以有publicprotecteddefault这些修饰符接口方法默认修饰符是public。你不可以使用其它修饰符。
main方法抽象方法可以有main方法并且我们可以运行它接口没有main方法,因此我们不能运行它。
多继承抽象方法可以继承一个类和实现多个接口接口只可以继承一个或多个其它接口
速度它比接口速度要快接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
添加新方法如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。如果你往接口中添加方法,那么你必须改变实现该接口的类。

异常处理 

异常是在程序执行期间发生的意外事件,是阻止当前方法或范围继续执行的问题,也叫运行时错误(Runtime error),例如用户输入无效信息或要打开一个不存在的文件。异常情形可以做的是跳出当前的上下文,并把这个问题转移上一级。这就是抛出一个异常时的操作。之后,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序。

捕获异常

如果发生异常而未处理,Java运行时系统将在打印适当的消息和运行时堆栈踪迹之后终止程序。堆栈踪迹显示异常发生时处于活动状态的一系列嵌套方法调用,如下例所示:

Exception in thread "main" java.lang.NullPointerException
    at java.util.ArrayList.toArray(ArrayList.java:358)
    at net.datastructures.HashChainMap.bucketGet(HashChainMap.java:35)
    at net.datastructures.AbstractHashMap.get(AbstractHashMap.java:62)
    at dsaj.design.Demonstration.main(Demonstration.java:12)

但在终止程序之前,堆栈跟踪中的每个方法都有机会捕获异常,或处理,或者传递给调用它的上一级方法。处理异常的一般方法是Try-Catch模块。每个exceptionType都是某个异常的类型,每个variable都是一个有效的Java变量名。如果抛出异常,异常处理机制将使用匹配异常类型的参数来寻找第一个处理程序。而且catch子句完成后,处理程序的搜索过程停止。注意,只有匹配上的catch语句才会被执行。所以异常的大小关系应为:Type1< Type2< Type3

try {
    guardedBody
} catch (exceptionType1 variable1) {
    remedyBody1
} catch (exceptionType2 variable2) {
    remedyBody2
} . . .

//两个异常情况使用相同的处理过程
catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
System.out.println("Using default value for n.");
}

抛出异常

throw new exceptionType(parameters);

public void ensurePositive(int n) {
    if (n < 0)
        throw new IllegalArgumentException("That's not positive!");
    // ...
}

当一个方法被声明时,可以显式声明在调用该方法期间可能抛出特定异常类型的可能性。不管该异常是直接来自该方法体中的throw语句,还是从该方法体中的辅助方法调用向上传播。这依赖于关键字throw(不要与实际的throw语句混淆)。下面的throws NumberFormatException警告用户异常情况的可能性,以便他们更好地准备处理可能出现的异常。

public static int parseInt(String s) throws NumberFormatException;

转型

 向上转型:转换将自动执行,不需要显式转换向下转型:需要显式转换,编译器可能无法验证转换的正确性。
T -> U

T和U是类,U是T的父类

T和U是接口,U是T的父接口

T是实现接口U的类

和U是类,U是T的子类

T和U是接口,U是T的子接口

T是接口,U是实现的类

举例CreditCard card = new PredatoryCreditCard(...);PredatoryCreditCard pc = (PredatoryCreditCard) card;
   

泛型

泛型通常避免显式转换的需要。将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。

public class ObjectPair {
    Object first;
    Object second;
    public ObjectPair(Object a, Object b) { // constructor
        first = a;
        second = b;
    }
    public Object getFirst( ) { return first; }
    public Object getSecond( ) { return second;}
    public static void main(String arg[]){
        ObjectPair bid = new ObjectPair("ORCL", 32.07);
        String stock = bid.getFirst( ); // illegal; compile error 返回的对象类型是Object
        String stock = (String) bid.getFirst( ); // narrowing cast: Object to String
    }
}

 

public class Pair<A,B> {
    A first;
    B second;
    public Pair(A a, B b) { // constructor
        first = a;
        second = b;
    }
    public A getFirst( ) { return first; }
    public B getSecond( ) { return second;}
    public static void main(String arg[]){
        Pair<String,Double> bid = new Pair("ORCL", 32.07);
        String stock = bid.getFirst( );
        double price = bid.getSecond( );
    }
}

泛型方法

泛型方法使得该方法能够独立于类而产生变化。如果泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法。要定义泛型方法,只需将泛型参数列表置于返回类型之前:

public class GenericMethods {
    public <T> void f(T x) {
        System.out.println(x.getClass().getName());
    }
    public static void main(String[] args) {
        GenericMethods gm = new GenericMethods();
        gm.f("");
        gm.f(1);
        gm.f(1.0);
        gm.f(1.0F);
        gm.f('c');
        gm.f(gm);
    }
} /* Output:
java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Float
java.lang.Character
GenericMethods
*///:~

内部类

可以将一个类的定义放在另一个类的定义内部,这就是内部类。有以下注意事项:1)成员内部类不能存在任何static变量或方法;2)内部类依附外部类,首先创建外围类才能创建内部类

public class CreditCard {
    private static class Transaction { /* details omitted */ }
        // instance variable for a CreditCard
    Transaction[ ] history; // keep log of all transactions for this card
}

迭代器

迭代器是一种抽象扫描一系列元素的过程,一次扫描一个元素。Java使用以下两种方法定义java.util.Iterator迭代器接口scanner类就实现Iterator<String>接口,其next( )方法返回一个字符串实例。

hasNext( )如果序列中还有一个元素,则返回true,否则返回false。while (iter.hasNext( )) {
    String value = iter.next( );
    System.out.println(value);
}
next( )返回序列中的下一个元素。
remove( )从集合中移除最近调用next( )返回的元素。此方法可用于筛选元素集合,例如丢弃数据集中的所有负数

单个迭代器实例只支持一次集合传递,无法将迭代器“重置”回序列的开头。希望允许重复迭代的数据结构可以支持每次调用新迭代器时返回新迭代器的方法。Java定义了参数化接口Iterable:

iterator( )返回集合中元素的迭代器

Java中的ArrayList是iterable(但本身不是iterator);它作为iterator( )方法的返回值生成迭代器。对iterator( )的每次调用都返回一个新的迭代器实例,从而允许对集合进行多次(甚至同时)遍历。

for (ElementType variable : collection) {
    loopBody // may refer to ”variable”
}

Iterator<ElementType> iter = collection.iterator( );
while (iter.hasNext( )) {
    ElementType variable = iter.next( );
    loopBody // may refer to ”variable”
}

ArrayList<Double> data; // populate with random numbers (not shown)
Iterator<Double> walk = data.iterator( );
while (walk.hasNext( ))
    if (walk.next( ) < 0.0)
        walk.remove( );

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值