Java基础
类设计技巧
- 一定要保证数据私有
- 一定要对数据初始化
- 不要在类中使用过多的基本类型
- 不是所有的域都需要独立的域访问器和域更改器
- 将职责过多的类进行分解
- 类名和方法名都要能够体现他们的职责
- 优先使用不可变的类
反射
Employee e
- Class c1 = e.getClass();
- Class c1 = Class.forName(e);
- Class c1 = Employee.class;
- c1.getName()得到类的名字
- Class c1 =Class.forName(e); 中利用newInstance创建对象:调用的类必须有无参的构造器 Object obj = c1.newInstance
- java.lang.reflect包中有三个类Field、Method、Constructor分别描述类的域、方法、构造器。都有getName方法,返回项目名。此包中的Modifier类中的isPublic、isPrivate或isFinal判断…
- Java反射机制是在运行状态中,
- 对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意一个方法和属性;
- 这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制
回调
public interface ServiceProvider {
public void customHint();
}
public class ChinaTelecom {
private ServiceProvider sp;//callback接口作为属性
public void setSp(ServiceProvider sp) {
this.sp = sp;
}
public void init(){
System.out.println("Welcome, This is ChinaTelecom! ");
sp.customHint();//sp自定义的操作
}
}
public class KongNet implements ServiceProvider {
public void customHint() {
System.out.println("优惠活动开始啦,即日起登陆空中网就有好礼送! 详情见网站公告。");
}
public static void main(String[] args) {
ChinaTelecom ct=new ChinaTelecom();
ct.setSp(new KongNet());//告诉ChinaTelecom这是哪家sp
ct.init();
}
}
序列化与反序列化
- 序列化流:把对象按照流一样的方式存入文本或者在网络中传输; 对象 —> 流
- 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。 流—> 对象
public class ObjectStreamDemo { public static void main(String[] args) throws IOException { // 序列化数据其实就是把对象写到文本文件 //write(); read(); } private static void read() throws IOException { // 创建反序列化流对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream( "D://a.txt")); // 读取,还原对象 try { Person p = (Person) ois.readObject(); System.out.println(p.toString()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } ois.close(); } private static void write() throws IOException { // 创建序列化流对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "D://a.txt")); // 创建对象 Person p = new Person("java", 20); oos.writeObject(p); // 释放资源 oos.close(); } }
接口
比较器
- 对象实现Comparable接口重写compareTo方法
- 自定义比较器实现Comparator接口,重写compare方法;或者使用匿名内部类:
Collections.sort(listMap, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { int compareTo = (o2.get("count")+"").compareTo(o1.get("count")+""); return compareTo; } });
对象克隆
使用clone()方法: 希望copy是一个新对象,初始状态与original相同,之后会有各自不同的状态使用clone();
Employee original = new Employee("John",500);
Employee copy = original.clone();
- 浅拷贝
class Employee implements Cloneable{ public Employee clone() throw CloneNotSupportedExecption{ return (Employee) super.clone(); } }
- 深拷贝
class Employee implements Cloneable{ public Employee clone() throw CloneNotSupportedExecption{ Employee cloned = (Emplyee)super.clone(); clonee.hireDay = (Date)hireDay.clone(); return cloned; } }
lambada表达式(小写的^)
- 带参数的lambda表达式
(String first ,String second) -> { if(first.length()<second.length())return -1; else if(first.length()>second.length())return 1; else return 0; }
- 使用
String[] str = new String[]{"Mefs","asdgsa","asdgasd","hasdfga"}; Arrays.sort(str,(first,second)->first.length()-second.length());
异常
Throwable
|-- Error
|-- Exception
|-- IOException
|-- 试图在文件尾部后面读取数据
|-- 试图打开一个不存在的文件
|-- 试图根据给定的字符串查找Class对象,而这个字符串并不存在
|-- RuntimeException
|-- 错误的类型转换
|-- 数组访问越界
|-- 访问null指针
java语言规范将派生于Error类或RuntimeException类的所有异常称为非受查异常,所有其他 的异常称为受查异常
泛型
泛型方法
class ArrayAlg{
public static <T> T getMiddle(T... a){
return a[a.length/2];
}
}
String middle = ArrayAlg.<String>getMiddle("John","Tom","jerry");
//可省略String
String middle = ArrayAlg.getMiddle("John","Tom","jerry");
集合
两个基本接口Collection和Map
- 迭代器
Collection<String> c = ...; Iterator<String> iter = c.iter.next(); while(iter.hasNext()){ String element = iter.next(); 。。。 } //用for each循环 for(String element:c) { ... }
- 链表
数组和数组列表都有一个重大的缺陷。就是从数组的中间位置删除一个元素要付出很大的代价,原因是数组中处于被删除元素之后所有元素都要向数组的前端移动。插入也是如此。 链表解决了这个问题
LinkedList.add方法将对象添加到链表的尾部;
LinkedList类的listIterator方法返回实现了ListIterator接口的迭代器 ;ListIterator接口有两个方法,反向便利链表(E previous() ; boolean hasPrevious();) 越过链表中的第一个元素,在第二个元素之前添加新的元素”Juliet”:
List<String> staff = new LinkedList<String>();
staff.add("Amy");
staff.add("Bob");
staff.add("Carl");
ListIterator<String> iter = staff.listIterator();
iter.next();
iter.add("Juliet");
缺点:不支持快速随机访问。虽然支持用get方法访问某个特定的元素,但是效率很低,每次需要从头搜索 使用数组或ArrayList对集合进行随机访问 —
- 散列集与树集
散列集 HashSet: 如果a.equals(b)为true,a与b必须具有相同的散列码,即a.hashCode()必须等于b.hashCode()。set类型,是没有重复元素的元素集合。set的add方法首先在集合中查找要添加的对象,如果不存在,就将这个对象添加。
树集 TreeSet:有序集合。排序方式:1.TreeSet(Comparator comparator) 带比较器;2.保存实现了Comparable接口的类的对象
- 队列、双端队列、优先级队列
JavaSE6中引入Deque接口,并由ArrayDeque和LinkedList类实现
PriorityQueue(int initialCapacity,Comparator c) 优先级队列中的元素可以按照任意的顺序插入,却总是按照排序的顺序进行检索。也就是说,无论何时调用remove方法,总会获得当前优先级队列中最小的元素。 但是并没有对所有元素进行排序;使用数据结构“堆heap”:可以自我整理的二叉树,对树执行添加和删除操作,可以让最小的元素移动到根,而不必花时间对元素进行排序。
映射(Map)
- 为映射的两个通用实现:散列映射HashMap、树映射TreeMap 均实现Map接口
- 散列稍快些,如果不需要按照排序顺序访问键,选择散列。
- 枚举一个映射的所有键:
Set<String> keys = map.keySet(); for(String key:keys){ 。。。 }
- 枚举条目避免查找值,同时查看键和值:
for(Map.Entry<String,Employee> entry : staff.entrySet()){ String k = entry.getkey(); Employee v = entry.getValue(); 。。。 }
视图与包装器
- java.util.Arrays
Arrays.asList();
- java.util.Collections 算法工具类
List<String> lists = Collection.nCopies(100,"DEFAULT");//100个默认DEFAULT Set<String> emptyset = Collection.emptySet(); //不可修改的视图 Collections.unmodifiableList(staff); //同步视图 Map<> map = Collections.synchronizedMap(new HashMap<>()); //受查视图 ArrayList<String> string = mew ArrayList<>(); List<String> safeString=Collections.checkedList(string,String.class);//防止插入一个错误的泛型
线程
多线程:一个程序同时执行多个任务。通常每一个任务称为一个线程。 进程与线程区别:每个进程拥有自己的一整套变量,而线程则共享数据。
Thread.sleep();//暂停当前线程活动
1.继承Thread类
2.实现Runnable接口
start()启动线程
volatile关键字为实例域的同步访问提供了一种免锁机制。如果一个域被声明为volatile,那么编译器和虚拟机就知道该域是可能被另一个线程并发更新的。