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方法。

浙公网安备 33010602011771号