JAVA-面向对象核心技术

1、类的封装

将对象的属性和行为封装起来的载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。比如,我们到餐厅去点餐,我们创建一个餐厅的对象,同时创建一个厨师的对象,用户可以进行点餐,然后就可以吃饭,但没办法知道厨师的具体信息,以及厨师如何做这道菜的。代码实现如下:

public class Resturant {
    Cook cook = new Cook();
    public void takeOrder(String dish){
        cook.cooking(dish);
        System.out.println("您的"+dish+"做好了,请慢用");
    }

    public String saySorry(){
        return "抱歉,本餐厅不提供此项服务";
    }

    public static void main(String[] args){
        Resturant res = new Resturant();
        System.out.println("请帮我做一份香辣肉丝");
        res.takeOrder("香辣肉丝");
        System.out.println("你们的厨师叫什么名字");
        System.out.println(res.saySorry());
    }
}



class Cook {
    private String name;
    public Cook(){
        this.name = "Tom Cruise";
    }
    private void cutUnion(){
        System.out.println(this.name + "切葱花");
    }
    private void washVegetables(){
        System.out.println(this.name + "洗蔬菜");
    }
    void cooking(String dish){
        this.washVegetables();
        this.cutUnion();
        System.out.println(this.name + "开始烹饪" + dish);
    }
}

输出为:

请帮我做一份香辣肉丝
Tom Cruise洗蔬菜
Tom Cruise切葱花
Tom Cruise开始烹饪香辣肉丝
您的香辣肉丝做好了,请慢用
你们的厨师叫什么名字
抱歉,本餐厅不提供此项服务

2、类的继承

继承的基本思想就是基于某个父类的扩展,制定出一个新的子类,子类集成父类原有的属性和方法,也可以增加原来父类所不具备的属性和方法,或者直接重写父类的某些方法。例如平行四边形是特殊的四边形,可以说平行四边形继承了四边形类,这是平行四边形类将四边形类的所有属性和方法都保留了下来,并基于四边形类扩展了一些新的属性和方法。
接下来,我们介绍继承的四个小的知识点

extends关键字
在java中,让一个类继承另一个类,用extends实现

方法的重写
重写就是在子类中将父类的成员方法的名称保留,重新编写成员方法的实现内容,更改成员方法的存储权限或者修改成员方法的返回值类型。
值得注意的一点是,修改方法的修饰权限时,只能从小变大,比如父类的权限是protected,那么子类的权限只能是public。

super关键字
如果子类重写了父类的方法,如果想调用父类的方法,可以使用super关键字。
同样,在构造函数中,使用super关键字可以调用父类的构造方法,而子类构造方法中的其他代码只能写在super之后。
在类的继承机制中,当实例化子类对象时,父类对象也相应被实例化,也就是说,会自动调用父类的无参构造方法,但是有参构造方法不能被调用,只能依赖于super关键字。

下面,我们基于一个例子来体会下上面所介绍的内容:

public class Pads extends Computer{
    String sayHello(){
        return super.sayHello() + "平板电脑";
    }

    public static void main(String[] args){
        Computer pc = new Computer();
        System.out.println(pc.sayHello());
        Pads pad = new Pads();
        System.out.println(pad.sayHello());
    }
}

class Computer{
    String sayHello(){
        return "欢迎使用";
    }
}

输出为:

欢迎使用
欢迎使用平板电脑

object类
在java中,所有类都直接或者间接继承了java.lang.Object类,它是所有类的父类,在Object类中,有几个比较重要的方法:
getClass().getName() : 该方法可以得到类的名称。
toString():toString()方法的功能是将一个对象返回为字符串形式。
equals():在object类中,equals方法实现的是==的功能,即比较两个对象的引用地址,所以如果想让equals方法比较的是对象的内容的话,需要对该方法进行重写。

3、类的多态

多态意为一个名字可具有多种语义,类的多态性可以从两个方面来体现:一是方法的重载,二是类的上下转型。

方法的重载:方法的重载就是在一个类中允许同时存在一个或者多个以上的同名方法,只要这些方法的参数个数或类型不同即可。方法的重载与方法的重写的区别要注意区分,重写指的是子类继承父类时,重新实现父类中的非私有方法。
如下面的代码,我们定义了多个add方法,由于add方法的参数类型、参数个数、参数顺序不同,都构成了方法的重载。

public class OverLoadTest {
    public static int add(int a) {
        return a;
    }

    public static int add(int a, int b) {
        return a + b;
    }

    public static int add(int a, double b) {
        return (int) (a + b);
    }

    public static double add(double a, double b) {
        return a + b;
    }

    public static int add(double a, int b) {
        return (int) (a + b);
    }

    public static int add(int... a) {
        int s = 0;
        for (int i : a) {
            s += i;
        }
        return s;
    }
}

向上转型
向上转型指把子类对象直接赋值给父类类型的变量,如定义一个四边形类Quadrangle和一个平行四边形类Parallelogram:

Quadrangle q = new Parallelogram()

与向上转型相对应的是向下转型,即把一个父类对象直接赋值给子类类型的变量,这往往是不可以的,正如平行四边形都是四边形,但不是四边形都是平行四边形一样,这样做是有危险的,我们需要显式强制转换才可以。

isinstanceof关键字
可以使用isinstanceof操作符来一个类是否是某个类的实例。

4、抽象类和接口

4.1 抽象类

通常说四边形具有4条边,或者更具体一点,平行四边形是具有对边平行且相等的特性的特殊的四边形,等腰三角形是其中两条边相等的三角形,但对于一般的图形对象,我们很难使用具体的语言去描述,它有几条边,究竟是什么图形,没有人能说清楚,这种类在java中被定义为抽象类。

使用abstract关键字定义的类称为抽象类,而使用abstract关键字定义的方法称为抽象方法。

在使用抽象类和抽象方法时,必须遵循下面的原则:
1)抽象类中,可以包含或者不包含抽象方法,但是包含抽象方法的类必须是抽象类。
2)抽象类不能直接被实例化
3)抽象类被继承后,子类需要实现其中所有的抽象方法
4)如果继承抽象类的子类也被声明为抽象类,则可以不用实现父类中所有的抽象方法。

下面是一个抽象类的代码:

public class goShopping {
    public static void main(String[] args){
        Market market = new WallMarket();
        market.name = "沃尔玛";
        market.goods = "七匹狼西服";
        market.shop();
        market = new TaoBaoMarket();
        market.name = "淘宝";
        market.goods = "韩都衣舍花裙";
        market.shop();
    }
}

abstract class Market{
    public String name;
    public String goods;
    public abstract void shop();
}


class TaoBaoMarket extends Market{
    @Override
    public void shop() {
        System.out.println(name +  "网购" + goods);
    }
}

class WallMarket extends Market{
    @Override
    public void shop() {
        System.out.println(name + "实体店购买" + goods);
    }
}

输出为:

沃尔玛实体店购买七匹狼西服
淘宝网购韩都衣舍花裙

4.2 接口声明及实现

接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中所有方法都没有方法体,接口使用interface关键字进行定义。而接口继承接口时,使用extends关键字,而类继承接口时,使用的是implements关键字。这里要注意区分。当子类实现接口时,必须实现接口中所有的方法。另外一点需要注意的是,接口中所有的变量都是static和final的,所以必须进行初始化,而实现接口的子类不能对接口中的变量进行重新赋值。
下面是一个接口的举例:

public class QuadrangleUseInterface {
    public static void main(String[] args){
        drawTest[] d = {new SquareUseInterface(),new ParallelogramgleUseInterface()};
        for(int i=0;i<d.length;i++){
            d[i].draw();
        }
    }
}


interface drawTest{
    public void draw();
}

class ParallelogramgleUseInterface implements drawTest{
    @Override
    public void draw() {
        System.out.println("平行四边形.draw()");
    }
}

class SquareUseInterface implements drawTest{
    @Override
    public void draw() {
        System.out.println("正方形.draw()");
    }
}

输出为:

正方形.draw()
平行四边形.draw()

可以看到,接口同样适用向上转型。

4.3 抽象类和接口的区别

1)子类只能继承一个抽象类,但可以继承多个接口。
2)一个类要实现一个接口必须要实现接口中的所有方法,但是抽象类只用实现抽象方法。
3)抽象类中的成员变量可以是各种类型,但是接口中的成员变量只能是public static final
4)接口中只能定义抽象方法,但是抽象类中可以定义非抽象方法
5)抽象类中可以有静态方法和静态代码块,接口中不可以
6)接口不能被实例化,没有构造方法,但抽象类可以有构造方法

5、访问控制

java中的访问控制符主要有public、protected、default、private,那么这四种访问控制符的访问权限如下表所示:

public protected default private
本类 可见 可见 可见 可见
本类所在包 可见 可见 可见 不可见
其他包中的子类 可见 可见 不可见 不可见
其他包中的非子类 可见 不可见 不可见 不可见

6、final关键字

定义为final的类不能被继承
final的方法不能被重写
用final声明的变量不能被改变,也就是说final声明的变量可以认为是常量。但这个常量是相对于一个对象来说的,要想使一个变量变为真正的常量,也就是对所有对象来说,其值都是一样的,应该定义为static final,如下面的例子中,两个对象的a1值是不一样的,但是a2是一样的。

import java.util.Random;
import static java.lang.System.out;

public class FinalStaticData {
    private static Random rand = new Random();
    private final int a1 = rand.nextInt(10);
    private static final int a2 = rand.nextInt(10);

    public static void main(String[] args){
        FinalStaticData fdata = new FinalStaticData();
        out.println("a1_value" + fdata.a1);
        out.println("a2_value" + fdata.a2);

        FinalStaticData fdata1 = new FinalStaticData();
        out.println("a1_value" + fdata1.a1);
        out.println("a2_value" + fdata1.a2);
    }
}

输出为:

a1_value3
a2_value6
a1_value0
a2_value6

7、内部类

如果类中再定义一个类,那么类中再定义的那个类被称为内部类,比如汽车和发动机的关系。内部类可以分为成员内部类、局部内部类和匿名类。

7.1 成员内部类

在成员内部类中,内部类可以随意使用外部类的成员方法以及成员变量,但是内部类的成员只有在内部类的范围之内的可知的,不能被外部类使用。内部类的对象实例化操作必须在外部类或外部类的非静态方法中实现。

public class OuterClass {
    innerClass in = new innerClass();
    public void ouf(){
        in.inf();
    }

    class innerClass{
        innerClass(){

        }
        public void inf(){

        }
        int y = 0;
    }

    public innerClass doit(){
        in.y = 4;
        return new innerClass();
    }

    public static void main(String[] args){
        OuterClass out = new OuterClass();
        OuterClass.innerClass in = out.doit();
        OuterClass.innerClass in2 = out.new innerClass();
    }
}

如果在外部类中定义的成员变量与内部类的成员变量名称相同,可以使用this关键字。下面的例子中,x是形参,this.x代表内部类的x,TheSameName.this.x++代表了外部类的成员变量x:

public class TheSameName {
    private int x = 5;
    private class Inner{
        private int x = 9;
        public void doit(int x){
            System.out.println(x) ;
            System.out.println(this.x);
            System.out.println(TheSameName.this.x++);
        }
    }
    public static void main(String[] args){
        TheSameName tsn = new TheSameName();
        TheSameName.Inner inner = tsn.new Inner();
        inner.doit(2);
    }
}

输出为:

2
9
5

7.2 局部内部类

内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或任意的作用域中均可以定义内部类。

interface OutInterface2{

}

public class OuterClass3 {
    public OutInterface2 doit(final String x){
        class InnerClass2 implements OutInterface2{
            InnerClass2(String s){
                s = x;
                System.out.println(s);
            }
        }
        return new InnerClass2("doit");
    }
}

7.3 匿名内部类

使用如下的语法创建内部类:

return new A(){
  //内部类体
}

7.4 静态内部类

在内部类堑添加修饰符static,这个内部类就变为静态内部类了,一个静态内部类中可以声明静态成员,但是在非静态内部类中不可以声明静态成员。静态内部类中不能使用外部类的非静态成员,所以静态内部类在程序开发中比较少见。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 1 面向对象No6 面向对象 OO Object Oriented 编程时以对象为单元,封装数据和逻辑,以此提...
    征程_Journey阅读 1,116评论 0 2
  • java继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继...
    863cda997e42阅读 653评论 0 1
  • 1、.java源文件: 一个以”.java“为后缀的源文件:只能有一个与文件名相同的类,可以包含其他类。 2、类方...
    Hughman阅读 1,441评论 1 9
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,558评论 18 399
  • 雨水带走了眼泪 徒留泛红的眼眸 拼命地跑着 ...
    落落zz阅读 271评论 0 2