java语法基础 - 第三部分

1.多态

多态(动态绑定): 可理解为子类向上转型转成基类并调用基类方法,实质调用的是父类被子类覆盖的方法。 —— private方法不会被重载、重写,故不会动态绑定、static方法、字段也无动态绑定

动态绑定是与对象相关联而不是——static是绑定类的。
构造函数也能动态绑定,不过这会招致难以意料得错误,如父类构造,用了未被初始化的子类字段值

class father {
    int a = 0;
    void draw() 
        {
            System.out.println("a= " + a);
     };
    father() {
        draw();
    }
}
 class son extends father {
    int b = 1;
    void draw {
        System.out.println("b= " + b);
    }
入口函数    son s = new son();
        //最后结果是:b = 0;
        //因为在初始化父类时,son类的对象s并还没有创建,更无从谈起初始化的 b=1

 

私有方法不会动态绑定:

class One extends Test{
    private void cout() {
        println( "One Cout()" );
    }
}

class Test {
    private void cout() {
        println( "Test Cout()" );
     }
     public static void main(String[] args) {
        Test test = new One();
        test.cout();   // output: Test Cout()   私有方法没有动态绑定
     }
}      
2.接口 - 解耦
抽象类abstract

只要类方法有关键词abstract修饰-不准写具体的实现,必须用同样的关键词abstract修饰类
继承的子类必须重写父类所修饰的那些方法,否则子类必须抽象修饰

接口interface
  • 接口类似抽象类,不过完完全全是只提供接口的“抽象类”,接口的使用,具体实现需像继承一样 用关键词 implements
  • 接口方法是 public权限、字段是final、static权限  则说明了接口中的字段是域了且能直接使用无须继承(像类中的静态变量一样使用
  • 接口中定义了 static修饰的方法 必须要有函数主体
  • 如果创建不带任何方法定义及成员变量的基类 → 优先选择这个基类定义为接口,而不是抽象类(能够定义方法)
  • 接口与接口之间能继承    方法签名同优先级:接口具体的方法 > 继承类的方法
  • 接口与接口之间能嵌套,定义方法时需指定内嵌的接口才行
  • 接口可以像类一样,可作为参数,可向上转型等 ——记住是实例方法,需创建对象调用
  • 同一个类可继承多个接口 —— 可覆盖更加具体的返回类型同名方法
  • 同名同返回的参数类型,不可以覆盖父类有关继承关系的方法
class Father {
    public void cout(Father father) {
        println("Father.cout()"};
     }
 }
 class Son extends Father {  //有两个方法,而不是一个方法,并没有覆盖cout()方法
    public void cout() {
        println("Son.cout()");
    }
 }
 
 Father father = new Father();
 Son son = new Son();
 son.cout(father);  //输出:Father.cout()
 son.cout(son);     //输出:Son.cout() 
class Father{}
class Son extends Father{}
interface One { Father get(); }
interface Two extends One { Son get(); }  //覆盖了One中的get()方法
interface Instrument {
    interface teacher {
        void name();
    }
    int a = 5;
    void play();
}

class wind implements Instrument, Instrument.teacher {    //内嵌接口需明确的指定
    public void play() {
        System.out.println(" wind's voice is wuwuwu " );
    }
    public void name() {
        System.out.println("我是内嵌teacher接口的方法");
    }
 }
 
 public class zhulei {
    static void cout(Instrument a) {         //接口类似类一样,也能让子类向上转型
        a.play();
    }
    public static void main(String[] args) {
        System.out.println(Instrument.a);  //输出的结果是5,说明接口字段(域)能直接使用无需继承后在使用——静态变量
        wind w = new wind();
        cout(w);                //因为该函数是静态函数,故调用该函数不用实例化对象。
    //输出 : wind's voice is wuwuwu
    }
 }

工厂模式

运用接口的工厂方法:好处多个不同的对象能用同一函数调用(如各种棋子的移动、各种自行车的移动)

interface Wager {
     void cast();
}
interface WagerFactory {
     Wager getWager();
}
class Coin implements Wager {
     public void cast() {
           Random a = new Random(50);
           int result = a.nextInt(2);
           switch(result) {
           case 0:print("coin'face is down"); break;
           case 1:print("coin'face is on");
           }
     }
}
class CoinFactory implements WagerFactory {
     public Wager getWager() {
           return new Coin();       //向上转型
     }
}
public class Factories {
     public static void cast(WagerFactory a) {      //多个不同对象同用一个方法,向上转型 
           Wager c = a.getWager();
           c.cast();
     }
     public static void main(String[] args) {
           CoinFactory cf = new CoinFactory();
           cast(cf);
     }
}

装饰模式
  • 四元素: 抽象组件(基础)、具体组件、抽象装饰类(包含具体组件)、具体装饰类(包含组件)
interface House{ void style(); }  //抽象组件

class ChineseStyle implements House { public void style() { println("Chinese's House"); }  //具体组件

class EuropeanStyle implements House { public void style() { println("European's Hosue"); }     //具体组件

class HouseDecorator implements House {         //抽象装饰类
    Hosue house;
    HosueDecorator( House hosue) [ this.house = house; }
    public void style() { house.style(); }
}

class RedDecorator implements HosueDecorator {      //具体装饰类
    RedDecorator(Hosue hosue) { super(house); }
    public void style() {
        println("red" + house.style() );
     }
 }






3.内部类
  • 外部类内的静态方法用到内部类的实例化,大前提是外部类已经有实例化(外部类对象)且引用名需提到外部类类名外类名.内部类名 引用名 = 外类实例.内类实例
public class Outer {
    public class Inner1{}
    class Inner2{}
    static class Inner3{}
    public  static void main(String[] args) {
        Outer outer = new Outer();
        
        Outer.Inner1 Inner1 = new Outer.Inner1();   //与下面两者效果一样,跟内部静态一样
        Outer.Inner1 Inner1 = outer.new Inner1();
        
        Outer.Inner2 inner2 = outer.new Inner2();    //普通内部类实例
        Outer.Inner3 inner3 = new Outer.Inner3();    //静态内部类实例
    }
}

  • this:前面指向的类名是谁则指向谁 例如:类名.this → 指向的是当前该类名对象的引用

  • 内部类虽然定义了private →意思是你不能自行生成创建该对象(new),不过其对外开放的public方法依然能调用。

  • 局部内部类(方法内定义类)

  • 匿名内部类(直接在成员方法返回一个对象)

interface father {
    void cout();
}
public class Test {
    public static father generator() {
        return new father() {             //直接返回一个class、interface父类对象(自动向上转型,意味的匿名内部类在外部类使用时仅仅只能用到父类的方法,而匿名内部类的的其他方法只能辅助父类的方法使用,仅仅是这样
            private int i = 6;
            public void cout() {
                System.out.println(i);
            };
    }
}

  • 工厂设计另一种方法: 外类中设置一个静态的公有变量用来引用外列对象生成器

interface factory { a generator(); }
public class a {                                
    public stataic factory ga = new factory() {   //到时直接用 静态变量ga 生成 a对象
        public a generator() { return new a(); }
    };

  • 嵌套类: 用关键词“ static "修饰的内部类,无外围类的引用

  • 应用程序框架: 被设计用于解决某类特定问题的一个类或一组类
    控制框架: 特殊的应用程序框架,解决响应事件的需求

    事件驱动系统: 用来响应事件的系统

解耦-虽然能隐藏子类的方法
interface Father {
    void a() {}
}

class Son implements Father {
    private void cout() {}
    public void a() {}
    public void b() {}
}

public static void main(String[] args) {
    Father father = new Son();
    //father.b();    不可调用,向上转型已经减少方法访问接口。
    Method[] methods = father.class.getDeclaredMethods()   //用反射能进行调用被封闭的方法接口。甚至是private都能调用
   Method m = father.class.getDeclaredMethod("cout");
   m.setAccessible(true);   //调用前需设置这个为 true
   m.invoke(father);     //私有调用成功
    
4.持有对象 — 容器
  • java容器类库用:快速报错:探查是否有多个进程同时修改容器不使用复杂的算法事后检查
    ConcurrentHashMap、CopyOnWriteArrayList/Set → 可避免" 共同修改异常“这个异常
  • 容器类的泛型,即使明确了泛型的类型得到的Class类型信息还是一样
  • 表明Class 只是保存定义数组时所写的泛型标识符,而不是自己在实例化类时的类型信息
Class a = new ArrayList<Integer>();
Class b = new ArrayList<String>();
if( a == b ) System.out.println("true");      //输出:true  Class运行时类型信息一样

容器
容器
第一种:每个位置只保存数据
第二种:每个位置保存(键、值)
接口:Collection - 父类、List(继承Collection)、Queue(队列)、Set(元素不重复)
Map(键值对,接口,关联数组)、ArrayList(数字关联 - 实现Collection、List)

容器中基本上实现或者继承了 Collection接口,故都可以向上转型为Collection

[外链图片转存失败(img-yPwSK9S0-1565843017475)(en-resource://database/980:1)]

JCF(Java collections framwork) 虚线:类的实现(implements)、接口的继承   实线:类的继承(extends)

Hashtable、Vector、Stack 这三个容器是老版本的,现在的目的:为了支持老程序,所以在新的程序最好别使用

  • ArrayList容器 保存的是父类对象的引用即 Object   

因为底层容器是数组:随机访问很快( 与长度无关 )、插入,迭代器( 慢 )
如果指定 泛型(类型,可多个) 就不能添加该类型之外的对象   ArrayLIst<类型/泛型>

  • Map(接口)的实现类: HashMap (最快的查找)、TreeMap (升序(键) 保存键值——始终保持键的排序状态、耗资源)- 基于红黑树、LinkedHashMap (插入顺序保存、保留HashMap的查找速度)- 基于链表

Map中的内部接口是在抽象类 AbstractMap实现
散列码(Hash):对象的int值 → 对象的某些信息进行转换而成(相对唯一)
TreeMap:唯一带有 subMap(参数) 方法的 Map类
LinkedHashMap:构造器参数true → 遍历则为LRU最近最少使用,否则为元素插入顺序遍历

  • List(接口)的实现类:

    • Arrays.asList() - 固定长度: 保存的单纯的是指针并非引用,故能set,修改并不能作用到原列表——无法取数据类型的列表(无法泛型化)    注意:这里返回的ArrayList是Arrays里面的内部类ArrayList,该内部类并没有重写add(),remove()等方法 —— 这个类单纯只是个包装器,实质类内对象依然是该数组引用

    • list(接口).subList(): 就是保存的原列表中的视图,一改两者都会改变(像视图跟基本表的关系)    返回的是ArrayList中的内部类SubList,该内部类重写了add, remove, set, 宛如一个可操作的列表 —— 依然只是ArrayList内的数组,不过他有add方法,该方法是每增加一次就创建的一个新的数组,重新赋值数组变量引用

    • LinkedList:执行插入、删除的速度比ArrayList快,随机访问较慢(链表)- 实现了栈(Stack)、队列(Queue)、双端队列(Deque) 的接口方法底层存储数据是:双向链表

  • Set(接口)的实现类

    • 具有Collection完全一样的接口  (继承了Collection、Iterator接口)
    • TreeSet( 保持比较排序顺序 - 元素必须实现Comparable接口 )
    • LinkedHashSet( 保持插入顺序 - 链表、元素定义hasCoide() )
    • HashSet(最快的查询速度 - 元素必须定义hasCode() —— 任何Object都有定义这个方法,无需担心)

    接口SortedSet —— TreeSet需实现的接口
    方法:

    1. comparator(): 返回该Set使用的 Comparator比较器
    2. first() / last(): 返回首/尾元素
    3. subSet(元素1,元素2): 返回 [元素1,元素2) 范围内的Set视图
    4. headSet(元素) / tailSet(元素): 返回小于该元素 或者 大于等于该元素 的Set视图
    • BitSet
      1. 存储“开关”信息
      2. 比本地数组稍微慢 - 最小容量64位

  • Queen(接口)的实现类 ——并发编程重要、可靠的将对象从一个区域传输到另一个区域
    • 不能把对象添加
    • 实现了LinkedList接口
迭代器:统一各种容器的处理方式的轻量级对象 [接口](设计模式)
  • next(): 局部类实现Iterator接口   父类“指针”整型 cursor = i + 1、返回局部成员 i

  • ListIterator实现类: 只能用于List的实现类、双向移动-“双指针” 、指定迭代器一开始指向的位置

继承容器类或实现接口时 记得加泛型 —— 否则只能传Object的参数

Iterable接口
  • 正因为容器类都实现了这个接口所以能用foreach遍历

所以说明要想要自己设定的容器类能实现遍历,则需新增 实现Iterable接口 – 其实就是写一个iterator()的方法

class squene implements Iterable<T> {          //这个类的实例能直接 foreach
    Integer[] number = { 1,2,3,4,5,6};
    public Iterator<Integer> iterator() {          //实现Iterable接口的方法
        return new iterator<Integer>() { 
            count = 0;
            public boolean hasNext() { return count < number.length; }
            public next() { return number[count++]; }
            public remove() {}
        };
   }
}

class Array2<T>{
    T[]  arrays;
    Array2(T[] a) {
        this.arrays = a;
    }
}

ListIterator - 允许正向反向遍历器接口

源码 - ArrayList 内部类 ListItr
在这里插入图片描述
[外链图片转存失败(img-Efcy2zxp-1565843017483)(en-resource://database/1086:1)]
[外链图片转存失败(img-F4hz26AR-1565843017489)(en-resource://database/1088:1)]

ArrayList中的Iterator实现类
(当前输出元素的序号)cursor = 0、 (即将输出的以下各元素的序号)lastRet = -1
hasNext():cursor != 容器长度
next():lastRet= cursor、cursor += 1
remove():ArrayList对象.remove(lastRet)、cursor = lastRet、lastRet = -1

cursor:下一个元素的序号lastRet:当前已经输出的元素序号


应用实例

Integer[] a = {1, 2, 3, 4, 5}
List<Integer> list = new ArrayList<Integer>( Arrays.asList(a) );
ListIterator<Integer> it = list.listIterator( list.size() );    //起始点为容器长度
while( it.hasPrevious() ) {             // 判断是否序号 = 0;
    System.out.print( it.previous() + " " );    
}     //output: 5,4,3,2,1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值