2020.8.19

一、接口、抽象类、实现类关系

  1、接口可以继承接口

  2、抽象类可以继承实体类,但前提是实体类必须有明确的构造函数;抽象类可以实现接口,不能继承接口

  3、一个接口可以继承多个接口 interface C extends A,B{};

    一个类可以实现多个接口class D implements A,B,C{};

    但是一个类只能继承一个类,不能继承多个类;

    在继承类的同时也可以实现接口class E extends D implements A,B,C{}

    

二、在JAVA中,基本类型(除了boolean外)可以自动转换的,转换形式为:byte,short,char – int --long–float–double这就是自动转换的顺序了,其中byte,short,char在运算时是自动转换为int型的,而int与long运算时自动转换为long型。从上可知,float与double运算时是自动转换为double再进行计算的,int与float运算时先转换为float再运算。也就是说,表述范围小的可以自动转换为表述范围大的,(表述范围不是指类型的大小)其次,如果你要得到某一类型的数值时,也可以通过强制转换来实现。

  例:float a = 5.5 + 5是否正确

   定义float变量的时候,一定要在数字后边加上 f ,因为实数默认的是double型的,5+5.5的结果是double型的,因此这里的计算结果为double,如需赋给float类型的a则需要进行强转

  

 

三、关于集合

 

 

   1、线程安全集合:Vector; Hashtable; StringBuffer

    非线程安全集合:ArrayList; LinkedList; HashMap; HashSet; TreeMap; TreeSet; StringBuilder

 

  2、Vector、ArrayList、LinkedList集合比较:

    Vector: 与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。Vector的扩容因子为2,而ArrayList扩容因子为1.5,因此如果数据扩充速度快则选择Vector更佳。

    ArrayList: 是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。

    LinkedList: 是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

 

  3、HashTable、HashMap集合比较

    HashMap: 采用数组方式存储key-value构成的Entry对象,无容量限制;非线程安全;遍历使用Iterator迭代器

    Hashtable: 线程安全;无论是key或者value都不能有空值存在;遍历使用Enumeration列举

 

  4、Iterator与ListIterator比较

    Iterator:只能正向遍历集合,适用于获取移除元素。

    ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。

 

  5、Map.Entry接口

    Map的entrySet()方法返回一个实现Map.Entry接口的对象集合。集合中每个对象都是底层Map中一个特定的键-值对。

    通过这个集合迭代,您可以获得每一条目的键或值并对值进行更改。但是,如果底层Map在Map.Entry接口的setValue()方法外部被修改,此条目集就会变得无效,并导致迭代器行为未定义。

 

  6、集合HashMap的三种方式:    

    HashMap<Integer,String> map= new HashMap<Integer,String>();

    map.put(1,"zhangsan");

    map.put(2,"lisi");

    map.put(3,"wangwu");

    //方式一:

    for(Map.Entry<Integer,String> entry : map.entrySet()){

        System.out.println(entry.getKey() + ":" + entry.getValue());

    }

    //方式二

    Set set = map.entrySet();        

    Iterator<Integer> i = set.iterator();         

    while(i.hasNext()){      

      System.out.println(map.get(i.next()));    

    }

    //方式三

    for (Integer key : map.keySet()) {  

      Integer value = map.get(key);  

      System.out.println("Key = " + key + ", Value = " + value);   

    }

 

四、位运算

  左移运算符(<<)

    定义:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。

    设 a=1010 1110,a = a<< 2 将a的二进制位左移2位、右补0,即得a=1011 1000。

    若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。

  右移运算符(>>)

    定义:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。

    例如:a=a>>2 将a的二进制位右移2位,左补0 或者 左补1得看被移数是正还是负。

    操作数每右移一位,相当于该数除以2。

 

五、实现多线程的两种方法

  第一种方法:继承Thread类

  方法步骤总结:

  • 定义一个类继承Thread;
  • 重写Thread类中的run方法,将需要被多线程执行的代码存储到该run方法当中。
  • 建立Thread类的子类创建线程对象。
  • 直接调用子类从Thread类继承的start方法,开启一个线程(调用该线程的run方法)。

  第二种方法:实现Runable接口

  Thread类有一个Thread(Runnable target)构造方法,在Runable接口类中只有一个run()方法。

  当使用Thread(Runnable target)方法创建线程对象时,需要为该方法传递一个实现Runnable接口的对象,这样创建的线程将调用那个实现了Runnable接口类对象中的run()方法作为其运行代码,而不再是调用Thread类中的run方法了。

  方法步骤总结:

  • 定义一个类实现Runnable接口,覆盖Runnable接口中的run方法,将线程要运行的代码存放在该run方法中;
  • 通过Thread类建立线程对象,将Runnable接口的子类实例对象作为实际参数传递给Thread类的构造方法。

  两种方式区别

  • 继承Thread: 线程代码存放Thread子类run方法中,且该run方法被调用。
  • 实现Runnable:线程代码存在实现了Runnable类接口的对象的run方法中,且该run方法被调用。

  注意:启动一个新的线程,不是直接调用Thread子类的对象的run方法,而是调用Thread子类对象的start方法。

  start方法是从Thread类中继承的方法,Thread类对象的start方法将产生一个新的线程,并在该线程上运行该Thread类对象中的run方法。

  根据面向对象的多态性可知,在该线程上实际运行的是我们编写的那个类(Thread的子类)对象中的run方法。

 

 

 

    

    

    

 

    

posted @ 2020-08-20 23:17  Rhettttt  阅读(120)  评论(0)    收藏  举报