Java基础语法最全解析

学习顶层,使用底层

1.学习顶层:学习顶层接口/抽象类中共性的方法所有的子类都可以使用

2.使用底层:顶层不是接口就是抽象类无法创建对象使用,需要使用底层的子类创建对象使用

常用关键字

final:最终、不可改变的

  1. 可以用来修饰一个类:表示此类不可继承

  2. 可以用来修饰一个方法:表示此方法不可覆盖重写

  3. 还可以用来修饰一个变量:变量变为常量

    • 对于基本类型来说,不可变说的是变量当中的数据不可改变
    • 对于引用类型来说,不可变说的是变量当中的地址值不可改变

常用类

String:字符串

注意:字符串是常量;它们的值在创建之后不能更改,字符串的底层是一个被final修饰的数组,不能被改变

常用string方法

valueOf('基础数据类型') // 将基础类型数据的文本转换为字符串

substring(int beginIndex) // 返回一个新的字符串,它是此字符串的一个子字符串。

getBytes(String charset) // 将string转换为byte 数组。

toLowerCase() // 将此 String 中的所有字符都转换为小写。

toUpperCase() // 将此 String 中的所有字符都转换为大写。

replace(char oldChar, char newChar)
		// 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。

trim() // 返回字符串的副本,忽略前导空白和尾部空白。

isEmpty() // 当且仅当 length() 为 0 时返回 true。

// 在字符串中查询指定子字符串的位置
charAt(int index) // 返回指定索引处的 char 值。
indexOf(string) // 返回指定字符在此字符串中第一次出现处的索引。

// 返回指定字符或字符串出现的索引位置
lastIndexOf(int ch)		// 返回指定字符在此字符串中最后一次出现处的索引。
lastIndexOf(int ch, int fromIndex)
	// 返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。

// 比较两个string类型内容
contains(CharSequence s) // 判断字符串是否包含指定的 char 值,返回 true。
equals(Object anObject) // 将此字符串与指定的对象比较。
equalsIgnoreCase(String anotherString) // 将此 String 与另一个 String比较,不考虑大小写。

// 判断是否以指定字符开头或者结尾
endsWith(String suffix) // 判断此字符串是否以指定的后缀结束。
startsWith(String prefix) // 判断此字符串是否以指定的前缀开始。

// 将字符串转换为字符数组,和字节数组
format(Locale l, String format, Object... args)
	// 格式字符串和参数返回一个格式化字符串。
getBytes(String charset) // 将string转换为byte 数组。
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
	// 将string转换为字符数组

toCharArray() // 将此字符串转换为一个新的字符数组。

// 正则表达式
matches(String regex) // 告知此字符串是否匹配给定的正则表达式。
replaceAll(String regex, String replacement)
    // 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

replaceFirst(String regex, String replacement)
	// 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

split(String regex) // 根据给定正则表达式的匹配拆分此字符串。

StringBuilder

注意:底层也是个数组,,但是没有被final修饰, 可以改变长度

append 方法始终将这些字符添加到缓冲区的末端;而 insert
方法则在指定的索引下添加字符。

StringBuffer(String str)// 构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
append(基础类型数据 b) // 将 基础类型的字符串表示形式追加到序列后面。
charAt(int index) // 返回此序列中指定索引处的 char 值。
delete(int start, int end) // 移除此序列的子字符串中的字符。
deleteCharAt(int index) // 移除此序列指定位置的 char。
insert(int offset, 基础类型数据 b) // 将基础类型参数的字符串表示形式插入指定位置中。
toString() // 返回此序列中数据的字符串表示形式。

StringBuffer

StringBuffer是线程安全的,性能低于StringBuilder

// 构造函数
StringBuffer()
	// 构造一个字符串缓冲区,其中没有字符,初始容量为16个字符。
StringBuffer(CharSequence seq)
	// 构造一个包含与指定字符相同的字符串缓冲区。
StringBuffer(int capacity)
	// 构造一个字符串缓冲区,其中没有字符,但是包含指定的初始容量capacity。
StringBuffer(String str)
	// 构造一个指定字符串内容的字符串缓冲区。
// +方法
StringBuffer append(boolean b)
	// 将boolean参数的字符串表示形式追加到序列中。
StringBuffer append(char c)
	// 将char参数的字符串表示形式追加到此序列。
StringBuffer append(char[] str)
	// 将char数组参数的字符串表示形式追加到此序列。
StringBuffer append(char[] str, int offset, int len)
	// 将char数组参数的子数组的字符串表示形式追加到此序列。
StringBuffer append(CharSequence s)
	// 将指定的内容附加CharSequence到此序列。
StringBuffer append(CharSequence s, int start, int end)
	// 将指定的子CharSequence序列追加到此序列。
StringBuffer append(double d)
	// 将double 参数的字符串表示形式追加到此序列。
StringBuffer append(float f)
	// 将float 参数的字符串表示形式追加到此序列。
StringBuffer append(int i)
	// 将int 参数的字符串表示形式追加到此序列。
StringBuffer append(long lng)
	// 将long 参数的字符串表示形式追加到此序列。
StringBuffer append(Object obj)
	// 附加Object参数的字符串表示形式。
StringBuffer append(String str)
	// 将指定的字符串追加到此字符序列。
StringBuffer append(StringBuffer sb)
	// 将指定的内容附加StringBuffer到此序列。
StringBuffer appendCodePoint(int codePoint)
	// 将codePoint参数的字符串表示形式追加到此序列。
int capacity()
	// 返回当前容量。
char charAt(int index)
	// 返回char指定索引处的此序列中的值。
int codePointAt(int index)
	// 返回指定索引处的字符(Unicode代码点)。
int codePointBefore(int index)
	// 返回指定索引之前的字符(Unicode代码点)。
int codePointCount(int beginIndex, int endIndex)
	// 返回此序列的指定文本范围内的Unicode代码点数。
StringBuffer delete(int start, int end)
	// 删除此序列的子字符串中的字符。
StringBuffer deleteCharAt(int index)
	// char按此顺序删除指定位置。
void ensureCapacity(int minimumCapacity)
	// 确保容量至少等于指定的最小值。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
	// 字符从此序列复制到目标字符数组中dst。
int indexOf(String str)
	// 返回指定子字符串第一次出现的字符串中的索引。
int indexOf(String str, int fromIndex)
	// 从指定的索引处开始,返回指定子字符串第一次出现的字符串中的索引。
StringBuffer insert(int offset, boolean b)
	// 将boolea参数的字符串表示形式插入此序列中。
StringBuffer insert(int offset, char c)
	// 将char参数的字符串表示形式插入此序列中。
StringBuffer insert(int offset, char[] str)
	// 将char数组参数的字符串表示形式插入此序列中。
StringBuffer insert(int index, char[] str, int offset, int len)
	// 将str数组参数的子数组的字符串表示形式插入到此序列中。
StringBuffer insert(int dstOffset, CharSequence s)
	// 将指定的内容CharSequence插入此序列中。
StringBuffer insert(int dstOffset, CharSequence s, int start, int end)
	// 将指定的子CharSequence序列插入此序列中。
StringBuffer insert(int offset, double d)
	// 将double参数的字符串表示形式插入此序列中。
StringBuffer insert(int offset, float f)
	// 将float参数的字符串表示形式插入此序列中。
StringBuffer insert(int offset, int i)
	// 将第二个int 参数的字符串表示形式插入到此序列中。
StringBuffer insert(int offset, long l)
	// 将long参数的字符串表示形式插入此序列中。
StringBuffer insert(int offset, Object obj)
	// 将Object 参数的字符串表示形式插入此字符序列。
StringBuffer insert(int offset, String str)
	// 将字符串插入此字符序列。
int lastIndexOf(String str)
	// 返回指定子字符串最后一次出现在字符串中的索引。
int lastIndexOf(String str, int fromIndex)
	// 返回指定子字符串最后一次出现在字符串中的索引。
int length()
	// 返回该字符串的长度(字符数)。
int offsetByCodePoints(int index, int codePointOffset)
	// 返回此序列中与代码点给定index的偏移量的索引codePointOffset。
StringBuffer replace(int start, int end, String str)
	// 用指定的字符替换此序列的子字符串中的字符String。
StringBuffer reverse()
	// 返回此字符序列的反向替换。
void setCharAt(int index, char ch)
	// 指定索引处的字符设置为ch。
void setLength(int newLength)
	// 设置字符序列的长度。
CharSequence subSequence(int start, int end)
	// 返回一个新的字符序列,它是该序列的子序列。
String substring(int start)
	// 返回一个新的String,包含此字符序列中当前包含的字符的子序列。
String substring(int start, int end)
	// 返回一个新的String,包含此序列中当前包含的字符的子序列。
String toString()
	// 返回表示此序列中数据的字符串。
void trimToSize()
	// 尝试减少用于字符序列的存储空间。

Math 数学工具类

static double abs(double num) // 获取绝对值

static double ceil(double num) // 向上取整

static double floor(double num) // 向下取整

static long round(double num) // 四舍五人

Ranom随机数

//获取0-9之间的随机数
int number = r.nextInt(10);
System.out.println(number);

//获取1-10之间的随机数
int num = r.nextInt(10)+1;
System.out.println(num);

date:日期和时间

  1. 毫秒值的作用:可以对时间和日期进行计算,可以日期转换为毫秒进行计算,计算完毕,在把毫秒转换为日期:(1000毫秒
    == 1秒)

  2. 把毫秒转换为日期:1天=24x 60 x 60 = 86400秒=86400 x 1000 = 86400000毫秒

方法:

new Date() // 获取当前系统的日期和时间
new Date(long date) // 传递毫秒值,把毫秒值转换为Date日期
Long getTime() // 把日期转换为毫秒值(相当于System. current TimeMillis()方法)

返回自1970年1月1日00:00:00 GMT以来此Date对象表示的毫秒数。

after(Date when)   // 测试此日期是否在指定日期之后。
before(Date when)  // 测试此日期是否在指定日期之前。
setTime(long time)  // 设置此 Date 对象,以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点。
toString()
// 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。

Calendar 日期工具类

1、获取Calendar实例

Calendar cal= Calendar.getInstance();

2、初始值

代码如下,值得指出的是由于我们的时区设置是GMT+8,所以打印格林威治时间得到的是1970-01-01
08:00:00.

Calendar cal = Calendar.getInstance();//得到当前时间  
cal.setTimeInMillis(0);//转换成格林威治时间

3、获取值

cal.get(Calendar.YEAR);//年  
cal.get(Calendar.MONTH) + 1;//月(必须要+1)  
cal.get(Calendar.DATE);//日  
cal.get(Calendar.HOUR_OF_DAY);//时  
cal.get(Calendar.MINUTE);//分  
cal.get(Calendar.SECOND);//秒  
cal.get(Calendar.DAY_OF_WEEK);//星期(Locale.ENGLISH情况下,周日是1,剩下自己推算)

注意:如果拿时间不是为了计算而是展示出来,肯定用SimpleDateFormart了,模式为yyyy-MM-dd
HH:mm:ss

4、设置值

cal.set(2013, 5, 4, 13, 44, 51);//年月日时分秒(月份0代表1月)  
cal.set(Calendar.YEAR, 2014);//年  
cal.set(Calendar.MONTH, 7);//月(月份0代表1月)  
cal.set(Calendar.DATE, 11);//日  
cal.set(Calendar.HOUR_OF_DAY, 15);//时  
cal.set(Calendar.MINUTE, 33);//分  
cal.set(Calendar.SECOND, 32);//秒
cal.getTimeInMillis() // 获取Calendar对象的毫秒值

5、运算值

cal.add(Calendar.YEAR, 1);//年  
cal.add(Calendar.MONTH, 1);//月  
cal.add(Calendar.DATE, 1);//日  
cal.add(Calendar.HOUR_OF_DAY, -1);//时  
cal.add(Calendar.MINUTE, 1);//分  
cal.add(Calendar.SECOND, 1);//秒  
cal.add(Calendar.DATE, 7);//周

DateFormat日期格式化抽象类

作用:格式化 (也就是日期-> string、解析(string->日期)

日期格式模式: yyyy年M月dd日 EEEE(星期) H时mm分ss秒

  1. String format(Date date): 将Date日期,格式化为符合模式的字符串

  2. Date parse(String source): 将字符串,解析为Date日期

DateFormat是一个抽象类需要使用,子类SimpleDateFormat 类创建对象

SimpleDateFormat(String pattern) //  SimpleDateFormat 构造pattern
:传递指定的模式,
y 年 M 月 d 日 EEEE (星期) H 时 m 分 s 秒
//1.创建s impLeDateFormat对象构造方法中传 递指定的模式
SimpleDateFormat sdf = new SimpleDateFormat( pattrn: "yyyy年M月dd日 HH时mm分ss秒");

//2.调用SimpleDateFormat对象中的方法format,按照构造方法中指定的模式,把Date日期格式化为符合模式的字符串(文本)
//  String format(Date date)按照指定的模式,把Date日期,格式化为符合模式的字符串
Date date = new Date();
String d = sdf.format(date);  // 将日期转换为string类型
System.out.println(date);//Sun Aug 08 15:51:54 CST 2088
System.out.println(d); //2088年08月08日15时51分54秒

Date类型之间的比较

@Test
public void test02(){
    Date date1 = new Date();
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR,2019);
    Date date2 = calendar.getTime();
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd EEEE HH:mm:ss");
    String format1 = format.format(date1);
    String format2 = format.format(date2);
    /* format1.compareTo(format2) = 1  表示date1时间大于date2
    *  format1.compareTo(format2) = 0  表示两个时间一致
    *  format1.compareTo(format2) = -1 表示date1小于date2
    * */
    System.out.println(format2.compareTo(format1));
}

System类

1.  public static long currentTimeMillis() 
    		// 返回以事秒为单位的当前时间。

2.  static void arraycopy(object src, int srcPos, object dest, int destPos, int length)
    		// 将数组中指定的数据拷贝到另-个数组中。
/**
    src:源数组
    srcPos:源数组中的起始位置(起始索引)。:
    dest :目标数组。
    destPos:目标数据中的起始位置。
    Length:要复制的数组元素的数量。
**/

Arrarys 数组工具类

  1. static String toString(数组对象) 按照默认格式,输出数组对象

  2. static void sort(数组对象)按照升序,进行排序

集合

在这里插入图片描述

学习集合的目标:

1.会使用集合存储数据,2.会遍历集合,把数据取出来,3.掌握每种集合的特性

集合框架的学习方式:

  1. 学习顶层:学习顶层接口/抽象类中共性的方法所有的子类都可以使用

  2. 使用底层:顶层不是接口就是抽象类无法创建对象使用,需要使用底层的子类创建对象使用

Collection接口:单列集合父类s

所有单列集合的共性方法,此接口没有索引

boolean add(E e): //把给定的对象添加到当前集合中。
void clear() //清空集合中所有的元素。
boolean remove(E e) : //把给定的对象在当前集合中删除。
boolean contains(E e) : //判断当前集合中是否包含给定的对象。
boolean isEmpty() : //判断当前集合是否为空。
int size() : //返回集合中元素的个数。
object[] toArray() : //把集合中的元素,存储到数组中。

List:接口

List接口的特点:

  1. 有序的集合,存储元素和取出元素的顺序是一致的(存储123 取出123)

  2. 有索引,包含了一些带索引的方法

  3. 允许存储重复的元素

list接口中带索引的特有方法

void add(int index, E element):// 将指定的元素,添加到该集合中的指定位置上。
E get(int index) :// 返回集合中指定位置的元素。
E remove(int index): // 移除列表中指定位置的元素, 并返回被移除的元素。
E set(int index, E element):
    // 用指定元素替换集合中指定位器的元素,返回值的更新前的元素。

注意:操作索引的时候,一定要防止索引越界异常

子类ArrayList

ArrayList
集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

子类Linkedlist
  • java.util.Linkedlist集合数据存储的结构是链表结构。增删快,查询慢

  • 注意:使用此方法不可以使用多态,多态是看不到子类特有方法的

LinkedList集合特有方法

public void addFirst(E e) ;// :将指定元素插入此列表的开头。
public void addLast(E e) // :将指定元素添加到此列表的结尾。
public E getFirst() // :返回此列表的第一个元素。
public E getlast() // :返回此列表的最后一个元素。
public E removeF irst() // :移除并返回此列表的第一个元素。
public E removelast() :// 移除并返回此列表的最后一个元素。
public E pop() :// 从此列表所表示的堆栈处弹出一个元素。
public void push(E e) // :将元素推入此列表所表示的堆栈。
public boolean isEmpty() // :如果列表不包含元素,则返回true。

set:接口

Set接口的特点:

  1. 不允许存储重复的元素

  2. 没有索引,没有带索引的方法,也就不能使用普通的for循环遍历

子类:HashSet

哈希表=数组+链表+红黑树(提高查询的速度) 哈希表的特点:速度快

HashSet特点:

  1. 不允许存储重复的元素,没有索引,没有带索引的方法,也不能使用普通的for循环遍历需要使用迭代器Iterator接口,或者使用正确for循环

  2. 是一个无序的集合,存储元素和取出元素的顺序有可能不一致

  3. 给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法
    ,建立自己的比较方式,才能保证HashSet集合中的对象唯一

Map<k, v>接口:双列集合父类

Map(也称为字典、关联数组)是用于保存具有映射关系的数据,保存两组值,key和value,这两组值可以是任何应用类型的数据。
  Map的key不允许重复(底层Map的keySet()返回的是key的Set集合,所以key不会重复),即Map中对象的任意两个key通过equals()方法得到的都是false。而,Map的value值是可以重复的(Map的底层values()方法返回类型是Collection,可以存储重复元素),通过key总能找到唯一的value,Map中的key组成一个Set集合,所以可以通过keySet()方法返回所有key。Set底层也是通过Map实现的,只不过value都是null的Map来实现的。

int size();  // 返回Map的key-value对的长度。
boolean isEmpty();  // 判断该Map是否为空。
boolean containsKey(Object key);  // 判断该Map中是否包含指定的key。
boolean containsValue(Object value);  // 判断该Map是否包含一个或多个value。
V get(Object key);  // 获取某个key所对应的value;若不包含该key,则返回null。
V put(K key, V value);  // 向Map添加key-value对,当Map中有一个与该key相等的key-value对,则新的会去覆盖旧的。
V remove(Object key);  // 移除指定的key所对应的key-value对,若成功删除,则返回移除的value值。
void putAll(Map<? extends K, ? extends V> m);  // 将指定的Map中的key-value对全部复制到该Map中。
void clear();  // 清除Map中的所有key-value对。
Set<K> keySet();  // 获取该Map中所有key组成的Set集合。
Collection<V> values();  // 获取该Map中所有value组成的Collection。
Set<Map.Entry<K, V>> entrySet();// 获取到Map集合中所有的键值对对象的集合(Set集合)。
boolean remove(Object key, Object value)// 删除指定的key-value对,若删除成功,则返回true;否则返回false

Map实现类

Map典型的实现类是HashMap、Hashtable(HashMap子类还有LinkedHashMap)、SortedMap子接口及实现类TreeMap、WeakHashMap、IndentityHashMap等。

Map有一个内部类Entry,该类封装了key-value对,有如下三个方法:

K getKey();	// 获取Entry中的key值;
V getValue();	// 获取Entry中的value值;
V setValue(V value);	// 设置Entry中的value值,并返回新设置的value值。
子类:HashMap集合

HashMap底层是数组+链表的形式,实现Map.Entry接口,数组是Entry[]数组,是一个静态内部类,Entry是key-value键值对(类似json对象),持有一个指向下一个元素的next引用,这就构成链表(单向链表)。
  HashMap底层是数组和链表的结合体。底层是一个线性数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。数组是Entry[]数组,静态内部类。Entry就是数组中的元素,每个
Map.Entry
其实就是一个key-value对,它持有一个指向下一个元素的引用next,这就构成了链表。根据指定的hash值找到在table中的索引;HashMap底层数组的长度是2^n,默认是16,负载因子为0.75,所以最大容量阈值threshold
= (int)(capacity *
loadFactor);16*0.75=12,当超过这个阈值的时候,开始扩容,即每次扩容增加一倍。

  • HashMap存储自定义类型键值,Map集合保证key是唯一的:作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一

String 类重写hashCode方法和equals方法,可以保证key唯一

value 可以重复(同名同年龄的人视为同一个)

LinkedHashMap

LinkedHashMap是HashMap的子类,使用双向链表维护key-value对的顺序(只是关注key的顺序),迭代顺序和key-value插入Map中的顺序保持一致。

子类:HashTable集合

Hashtable是和HashMap一样,属于Map典型的实现类,区别于Hashtable是线程安全的Map实现,但是性能低。Hashtable不允许使用null作为key和value;若将null值存入Hashtable,会抛出NullPointerException异常;而HashMap可以使用null作为key或value。

Properties

Properties类是Hashtable类的子类。通常作为处理属性配置文件比较好。可以将Map对象中的key-value配置写入到属性文件中,反之,也可以将属性文件中的key=value加载到Map对象中。注意,属性文件中的属性key-value只能是字符串类型。提供以下几个方法来操作Properties

synchronized Object setProperty(String key, String value)
	// 设置属性值,底层是通过put来实现。
String getProperty(String key)// 获取指定属性名的属性值,底层是通过Map的get(Object key)来实现。
String getProperty(String key, String defaultValue)// 类似于getProperty(String key)方法,在此基础上多一个功能是党Properties中不存在指定的key时,该方法指定默认值去获取。
synchronized void load(InputStream inStream) throws IOException:
	// 从属性文件以输入流的方式加载key-value对,并将这些key-value追加到Properties中。
void store(OutputStream out, String comments)// 将Properties中的key-value对以输出流的方式输出到指定的属性文件中。

Collections:集合工具类

常用方法

  1. static <T> boolean addAll(需要添加元素的集合对象,Jπ… elements)

往集合中添加一些元素。

static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。

static <T> void sort(List<T> list) :将集合中元素按照默认规则排序。
static <T> void sort(List<t> list, Comparator<? super T> ) :

将集合中元素按照指定规则排序。

Iterator接口:迭代器

  1. Collection接口中有一个方法,叫iterator(),这个方法返回的就是选代器的实现类对象,所有集合对象都有此方法
    iterator() 返回Iterator接口对象

  2. boolean hasNext() :如果仍有元素可以迭代,则返回true。

  3. next() : 取出下一个元素。

集合线程安全问题

Vector、HashTable、Properties是线程安全的;

ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是线程不安全的。

值得注意的是:为了保证集合是线程安全的,相应的效率也比较低;线程不安全的集合效率相对会高一些。

enum枚举

public class ProductConstant {
    //  定义一个简单枚举
    public enum  AttrEnum{
        ATTR_TYPE_BASE(1,"基本属性"),
        ATTR_TYPE_SALE(0,"销售属性");

        private int code;
        private String msg;

        AttrEnum(int code,String msg){
            this.code = code;
            this.msg = msg;
        }

        public int getCode() {
            return code;
        }

        public String getMsg() {
            return msg;
        }
    }
}

面向对象

1 Java中有四种权限修饰符

public 公共的 > protected 不同包子类 > (default) 同一个包中 > private
同一个类中

注意事项: (default)并不是关键字“default”,而是根本不写。

2 this:本类

  1. 在本类的成员方法中,访问本类的成员变量。

  2. 成员方法中,访问本类的另一个成员方法。

  3. 本类的构造方法中,访问本类的另一个构造方法。

在第三种用法当中要注意:

A:this(… )调用也必须是构造方法的第一一个语句,唯一一个。

B:super和this两种构造调用,不能同时使用。

3 super:父类

  1. 在子类的成员方法中,访问父类的成员变量。

  2. 在子类的成员方法中,访问父类的成员方法。

  3. 在子类的构造方法中,访问父类的构造方法。

4 extends:继承

继承:子类共性抽取形成父类或者是接口(注意:在继承中只有子类知道父类是谁,父类并不知道他的子类是谁)

  1. 在Java中一个子类的直接父类是唯一的,但是一个父类可以拥有很多个子类,和父类。

  2. 注意:一个子类继承父类后,父类的所有都是子类的。

  3. 成员变量不能覆盖重写

5 abstract:抽象类,抽象方法

  1. 抽象类:在类名前加abstract关键字,可以定义抽象方法,和普通方法,和属性

  2. 抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。抽象方法必须在抽象类中,

  3. 抽象类不能直接创建抽象对象,必须用一个子类来继承抽象父类,然后向上转型为父类对象(抽象对象)。

6 interface:接口

public interface 接口名称{
	接口内容可以包含(抽象方法[abstract],常量[final],静态方法[static])
}
  1. 接口就是多个类的公共规范。

  2. 接口当中的抽象方法,修饰符必须是两个固定的关键字: public abstract,可以省略

  3. 不可以直接new一个接口对象,必须利用子类向上转型为接口对象,实现接口必须实现接口的抽象方法

  4. 接口是没有静态代码块或者构造方法的。

  5. implement:实现接口实现接口必须覆写接口中的全部抽象方法

  6. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。接口之间用逗号分隔。

  7. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。

  8. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象
    类,

  9. 如果实现类所实现的多个接口当中,
    存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。

  10. 类与接口之间是多实现的。一个类可以实现多个接口,接口与接口之间是多继承的。一个接口可以继承多个接口

  11. 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,(
    而且带着default关键字)

default:接口的默认方法

  1. 从Java 8开始,接口里允许定义默认方法。

格式:

public default 返回值类型 方法名称(参数列表) { 方法体 }

  1. 默认方法不需要子类覆写,但是会被子类继承此方法,并且可以在子类覆盖重写,默认方法主要用于接口的升级

static:接口的静态方法

  1. 从Java 8开始,接口当中允许定义静态方法。

格式:

public static 返回值类型 方法名称(参数列表) { 方法体 }

  1. 直接使用接口 类名称.静态方法()调用接口静态方法

private:接口的私有方法

  1. 我们需要抽取一个共有方法,用来解决接口中,两个默认方法之间重复代码的问题。但是这个共有方法不应该让实现类使用,应该是私有化的。

  2. 从Java 9开始,接口当中允许定义私有方法。

  3. .private普通私有方法,解决多个默认方法之间重复代码问题

格式:

private 返回值类型 方法名称(参数列表) { 方法体 }

  1. .private static静态私有方法,解诀多个静态方法之间重复代码问题

格式:

private static 返回值类型方法名称(参数列表) { 方法体 }

public static final:接口中的全局常量

  1. 接口当中也可以定义“成员变量”,但是必须使用public static
    final三个关键字进行修饰,可以省略。全局变量名称使用大写字母

  2. 直接使用接口名.接口全局常量名

7 多态

  1. 代码当中体现多态性,其实就是一句话: 父类引用指向子类对象

格式:

  1. 父类名称 对象名= new 子类名称();

  2. 接口名称 对象名= new 实现类名称();

  3. 对象名.方法名()
    ->优先调用覆写的方法,没有则向上查找,不能调用子类特有方法,只能调用父类拥有的方法,或者子类覆写的此父类的方法,

  4. 对象名.属性名 ->直接调用对象的属性,没有则向上查找

  5. 好处:无论右边new的时候换成哪个子类对象,等号左边调用方法都不会变化。

instanceof对象和类型的判断

  1. instanceof通过返回一个布尔值来,判断一个对象是否是指定类的对象,用要用来判断一个对象是否可以向下转型我其他类型

用法:

对象 instanceof 类型
:这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。

内部类

1 成员内部类

成员内部类:在一个类中,方法外,再定义一个类为成员内部类

  1. 注意:内用外,随意访问;外用内,需要内部类对象。

  2. 创建内部类对象

外部类名称.内部类名称对象名 = new 外部类名称()。new 内部类名称();

  1. 内部类调用外部类属性或者方法

外部类名称。this。属性 | 方法()

局部内部类

如果一个类是定义在一个方法内部的,那么这就是一个 局部内部类。

  1. “局部内部类”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。

  2. 局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是[有效final的]。原因:
    new出来的对象在堆内存当中,局部变量是跟着方法走的,在栈内存当中,方法运行结束之后,立刻出栈,局部变量就会立刻消失。但是new出来的对象会在堆当中持续存在,直到垃圾回收消失,因此局部内部类会复制一份在内部类中需要使用的在方法中的变量,以需后用,因此方法中的变量必须使用final关键字定义(java1.8后不写以可以)

3 匿名内部类

如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略掉该类的定义,而改为使用[匿名内部类]。

匿名内部类的定义格式:

接口名称 对象名 = new 接口名称() {
		//覆盖重写所有抽象方法
};
  1. 匿名内部类是省略了[实现类/子类名称],但是匿名对象是省略了[对象名称],两者不一样

多线程

线程常用方法

static void **sleep**(long millis) // 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
static Thread currentThread()  // 返回对当前正在执行的线程对象的引用。
string getName() // 返回该线程的名称。
setName(线程名字) // 设置线程的名称

object支持线程方法

  1. static wait(等待时间)不输入参数,线程则进入无限等待状态

  2. static notify()使线程进入唤醒状态(首先进入堵塞状态,然后进入运行状态)

image-20201130213448125

Thread:线程类

实现步骤:

  1. 创建一个Thread类的子类,并重写Thread类中的run方法,设置线程任务(开启线程要做的内容)
    注意:run方法在线程对象调用start方法后触发执行

  2. 创建Thread类的子类对象,调用Thred类中的方法start方法,开启新的线程,执行run方法

image-20201130213456754

Runnable:线程接口

实现步骤:

  1. 创建一个Runnable接口的实现类

  2. 在实现类中重写Runnable接口的run方法,设置线程任务

image-20201130213505360

3.创建一个Runnable接口的实现类对象

4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象

5.调用Thread类中的start方法,开启新的线程执行run方法

image-20201130234747315

Callable 接口

(1)实现Callabel接口

image-20201130213512155

(2)执行线程对象,并获取返回结果

image-20201130213517994

线程池(最优)

注意:以上三种方法,都太浪费系统资源,在业务代码里面,以上三种启动线程的方式都不能不用。[将所有的多线程异步任务都交给线程池执行]

image-20201130213525119

image-20201130213530504

CompletableFuture 异步编排(重点)

CompletableFuture的优点:

●异步任务结束时,会自动回调某个对象的方法

●异步任务出错时,会自动回调某个对象的方法

●主线程设置好回调后,不再关心异步任务的执行

基本使用

(2)从线程池中获取线程,并感知异常,但是不能修改返回的数据

image-20201130213537665

修改线程返回结果以及异常信息

(2) 从线程池中获取线程,并感知异常,而且可以修改线程返回的信息

image-20201130213543442

线程串行化方法

线程安全问题(核心)

  • 多个线程同时访问同一资源,会出现线程安全问题
  1. 使用Lock锁接口

ReentrantLock implements Lock接口

使用步骤:

  • 在成员位置创建一个ReentrantLock对象

  • 在可能会出现安全问题的代码前调用Lock接口中的方法lock()获取锁

  • 在可能会出现安全问题的代码后调用Lock接口中的方法unlock()释放锁

  1. 使用同步方法

使用步骤:

  • 把访问了共享数据的代码抽取出来,放到一个方法中

  • 在方法上添加synchronized修饰符

使用同步代码块

synchronized(锁对象){
	可能会出现线程安全问题的代码(访问了共享数据的代码)
}

注意:

1、通过代码块中的锁对象,可以使用任意的对象,只能锁住同一个锁对象实例的线程,否则无法锁住

2、但是必须保证多个线程使用的锁对象是同一个

3、锁对象作用:把同步代码块锁住,只让相同锁对象实例的,一个线程在同步代码块中执行,其他线程则等待,

IO编程

File类:文件,文件夹

  • 重点: file:表示文件 directory:表示,文件夹/目录 path:表示路径

路径是不区分大小写windows使用反斜杠,反斜杠是转义字符,两个反斜杠代表一个普通的反斜杠

创建删除功能的方法

File(String pathname) // 通过将给定路径名(字符串)创建一个新File 实例。
boolean createNewFile() // 不存在此文件,则创建一个新的空文件,不能创建文件夹
boolean delete()// 删除由此File表示的文件或目录。
boolean mkdirs() // 创建由此File表示的目录,包括任何必需但不存在的父目录。

注意:在创建文件和文件夹创建文件,的路径和名称在构造方法中给出(构造方法的参数)

获取功能的方法

  1. string getAbsolutePathQ() :返回此File的绝对路径名字符串。

  2. string getPath() : 将此File转换为路径名字符串。

  3. string getName() : 返回由此File表示的文件或目录的名称。

  4. long length() 返回由此File表示的文件的长度。

判断功能的方法

  1. boolean exists() :此File表示的文件或目录是否实际存在。

  2. boolean isDirectory() : 此File表示的是否为目录。

  3. boolean isFile() : 此File表示的是否为文件。

目录的遍历

  1. String[] list() : 返回一个String数组,表示该File目录中的所有子文件或目录。

  2. File[] listFiles() : 返回一个File数组,表示该File目录中的所有的子文件或目录。

注意:list方法和ListFiles方法遍历的是构造方法中给出的目录,如果构造方法中给出的目录的路径不存在,会抛出空指针异常,如果构造方法中给出的路径不是一个目录,也会抛出空指针异常

OutputStream抽象类:字节输出流

  • 流:数据(字符,字节) 1个字符=2个字节,1个字节=8个二进制位

注意:OutputStrem抽象类:是所有字节输出流的父类

定义了一些子类共性的成员方法:

  1. void close() : 关闭此输出流并释放与此流相关联的任何系统资源。

  2. void flush() :刷新此输出流并强制任何缓中的输出字节被写出。

  3. void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。

  4. void write(byte[] b, int off, int len)
    :从指定的字节数组写入Len字节,从偏移量off开始输出到此输出流。

  5. abstract void write(int b) : 将指定的字节输出流。

FileOutputStream:子类

字节输出流的使用步骤(重点):

  1. 创建一个File0utputStream对象,构造方法中传递写入数据的目的地

  2. 调用FileoutputStream对象中的方法write,把数据写入到文件中

  3. 释放资源(流使用会占用一一定的内存,使用完毕要把内存清空,提供程序的效率)

构造方法:创建FileOutputStream对象

  1. FileoutputStream(String name
    )创建一个向具有指定名称的文件中写入数据的输出文件流。

  2. FileoutputStream(File file) 创建一个向指定File
    对象表示的文件中写入数据的文件输出流。

追加写/续写:使用两个参数的构造方法

  1. FileoutputStream(String name, boolean append) 创建一个向具有指定 name
    名的文件中写入数据的输出文件流,并设置是否可以进行续写

  2. FileoutputStream(File file, boolean append) 创建一个向指定File
    对象表示的文件中写入数据的文件输出流,并设置是否进行续写

InputStream抽象类:字节输入流

注意:InputStream是所有输入流的父类

定义了所有子类共性的方法:

  1. int read( ) 从输入流中读取数据的下一个字节。

  2. int read(byte[] b) 从输入流中读取的字节保存在数组b中。

注意:没有数据后返回-1,否则返回读取到的字节

  1. void close() 关闭此输入流并释放与该流关联的所有系统资源。

FileInputStream:子类

构造方法:

  1. FileInputStream(String name) 接收需要读取的文件路径,

  2. FiLeInputStream(File file) 接收一个File对象,创建对象

Reader抽象类:字符输入流

  1. public void close() ;关闭此流并释放与此流相关联的任何系统资源。

  2. public int read()]: 从输入流读取一个字符,没有数据返回-1

  3. public int read(char[] cbuf):
    从输入流中读取一些字符,并将它们存储到字符数组cbuf中。没有数据返回-1

需要使用FileReader子类实例化对象

Writer抽象类:字符输出流

共性的成员方法:

  1. void write(int c) 写入单个字符。

  2. void. write(char[] cbuf)写入字符数组。

  3. abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,
    off数组的开始索引,len写的字符个数。

  4. void write(String str)写入字符串。

  5. void write(Sstring str, int off, int len)
    写入字符串的某一部分,off字符串的开始索引,len写的字符个数。

  6. void flush( )刷新该流的缓冲。

  7. void close() 关闭此流,但要先刷新它。

Filewriter类构造方法:

  1. Filewriter(File file )根据给定的File 对象构造一-个FileWriter 对象。

  2. Filewriter(String fileName) 根据给定的文件名构造一个Filewriter 对象。

续写,使用两个参数的构造方法

  1. Filewriter(String fileName,boolean append) append指定是否续写

  2. Filewriter(File file, boolean append) true为续写

Properties:集合

  • Properties集合extends Hashtable<k, v> implements Map<k, v>

Properties类表示了一一个持久的属性集。Properties
可保存在流中或从流中加载,Properties集合是一个双列集合,key和value默认都是字符串

  1. void store(Writer writer,String null)

把集合中的临时数据,持久化写入到硬盘中存储

  1. load(Reader red, String null),

把硬盘中保存的文件(键值对),读取到集合中使用

  1. object setProperty(String key, String value) 添加数据

  2. string getProperty(String key) 通过key找到value值,

  3. Set<String> stringPropertyNames() 返回此属性列表中的key集合,

PrivateStream:打印流

构造方法:

  1. Printstream(File file):输出的目的地是一个文件

  2. Printstream(outputstream out ) :输出的目的地是一个字节输出流

  3. Printstream(String fileName) :输出的目的地是一个文件路径

JDBC数据库编程

DriverManager :驱动管理对象

  1. Class.forName(数据库驱动) 加载驱动

  2. 获取数据库连接:

方法: static Connection getConnection(String url, String user, string
password)

参数:url :指定连接的路径(jdbc:mysql://ip地址(域名) :端口号/数据库名称)

​ user:用户名,

​ password:用户密码

例子: jdbc:mysql://localhost :3306/db3

Connection :数据库连接对象

  1. 获取执行sq1的对象

    Preparedstatement prepareStatement(String sql)

  2. 管理事务:

    setAutoCommit( boolean autoCommit): 参数为false,即开启事务

  3. 提交事务: commit() 回滚事务: rollback()

ResultSet :结果集对象

  1. Boolean next(): 游标向下移动一行,并判断当前行是否是最后一行

  2. get数据类型(字段名|数据集合索引) :

    ​ 通过索引(从1开始),或者字段名获取数据,

preparedstatement :执行sq1的对象

  1. 注册驱动,获取数据库连接对象Connection

  2. 定义sql,注意:sql的参数使用?作为占位符。

如: select * from user where username = ? and password = ?;

  1. 获取执行sql语句的对象

Preparedstatement Connection对象.prepareStatement(String sql)

  1. 给?赋值: Preparedstatement对象。set数据类型(int,值)

  2. 执行sql,接受返回结果,不需要传递sq1语句

  3. 处理结果

  4. 释放资源

DataSource接口:数据库连接池

注意:一般我们不去实现它,由数据库厂商来实现

连接池:1. C3P0 :数据库连接池技术,2. Druid
:数据库连接池实现技术,由阿里巴巴提供的

  1. getConnection() 获取连接:

  2. 归还连接:如果连接对象Conpection是从连接池中获取的,那么调用Connection对象。close()方法,
    则不会再关闭连接了。而是归还连接

使用Druid :数据库连接池

  1. 导入jar包druid-1.0.9.jar

  2. 定义配政文件:

是properties形式的

可以叫任意名称,可以放在任意目录下

  1. 获取数据库连接池对象:通过工厂来来获取

DruidDataSourceFactory

  1. 获取连接: getConnection

Java8 新特征

(一)Lambda表达式

面向对象的思想:做一件事情,找一个能解决这个事情的对象调用对象的方法,完成事情.

函数式编程思想:只要能获取到结果,谁去做的,怎么做的都不重要,重视的是做什么,而不是怎么做(将关注点从”怎么做”回归到"做什么”的本质上)

使用Lambda表达式

  • Lambda表达式的标准格式:(参数列表) -> {一些重写方法的代码};

a.一些参数,b.一个箭头,c.一段代码

解释说明格式: (必须为函数式接口才可以使用Lambda表达式)

():接口中抽象方法的参数列表,没有参数就空着;有参数就写出参数,多个参数使用逗号分隔

-> :传递的意思,把参数传递给方法体{}

{}:重写接口的抽象方法的方法体

函数式接口

注意:函数式接口:有且只有一个抽象方法的接口,称之为函数式接口,当然接口中可以包含其他的方法(默认静态,私有)

@FunctionalInterface注解:作用:可以检测接口是否是一个函数式接口

函数式编程

可以使用Lambda作为方法的参数和返回值

  • Lambda表达式的标准格式: (参数列表) -> {一些重写方法的代码};
  1. 方法的参数类型是一个函数式接口, 所有我们可以传递一个Lambda表达式

  2. 方法的返回值类型是一个函数式接口,所有我们可以返回一个Lambda表达式

Consumer<T> :消费型接口

void accept(T t);

image-20201130213650760

Supplier<T> :供给型接口

T get();

image-20201130213658883

Function<T, R> :函数型接口

R app1y(T t);

image-20201130213705400

Predicate<T> :断言型接口

boolean test(T t);

image-20201130213713707

(二)方法引用

方法引用:若Lambda体中的内容有方法已经实现了,我们可以使用"方法引用"
(可以理解为方法引用是Lambda表达式的另外一种表现形式)

image-20201130213721432

(三)Stream API步骤

流(Stream)到底是什么呢:是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算!”

注意:

①stream自己不会存储元素。

②Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。,

③Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

1、创建Stream

Stream主要用来操作集合,数组的

image-20201130213731574

2、中间操作

image-20201130213737621

filter 过滤
  • 接收lambda表达式,从流中排除不符合条件的元素

image-20201130213744083

limit(n) 截断流
  • limit 方法可以对流进行截取,只取用前n个

image-20201130213749972

skip(n) 跳过元素
  • 返回一个过滤前n个,诺流中元素不足n个,则返回一个空流对象

image-20201130213755241

distinct 筛选
  • 通过流所生成元素的hashCode()和equals()方法进行去重操作

image-20201130213801279

map 映射(重要)
  • map:接收Lambda表达式,将元素提取到流中。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

flatMap:接收一个函数作为参数, 将流中的每个值都换成另一个流,
然后把所有流连接成一个流

image-20201130213809015

/*审核人封装*/
public List<Map<String, Object>> index4(ProcessList process) {
    /*从数据库获取数据*/
    List<Reviewed> revieweds = redao.findByReviewedTimeNotNullAndProId(process);

    /*获取集合流*/
    List<Map<String, Object>> relist = revieweds.stream()
        .map(r -> {                /*使用map映射,表示集合中的每一个元素都会执行代码块中的操作*/
            Map<String, Object> result = new HashMap<>();
            User u = udao.findById(r.getUserId().getUserId()).get();
            Position po = pdao.findById(u.getPosition().getId()).get();
            SystemStatusList status = sdao.findById(r.getStatusId()).get();
            result.put("poname", po.getName());
            result.put("username", u.getUserName());
            result.put("retime", r.getReviewedTime());
            result.put("restatus", status.getStatusName());
            result.put("statuscolor", status.getStatusColor());
            result.put("des", r.getAdvice());
            result.put("img", u.getImgPath());
            result.put("positionid", u.getPosition().getId());
            return result;                 /*将每一个元素,返回出去*/
        }).collect(Collectors.toList());        /*将流生成为list集合*/

    return relist;
}

sorted 排序

(1)sorted() 自然排序(按照compareto()方法进行排序)
流元素必须实现Comparable接口,

(2)sorted(Comparator com) 定制排序

image-20201130213901352

concat 组合
  • 如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat

static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T>
b)

总结
logger.warn("*********************过滤*********************");
all.stream()
    .filter(a -> a.geteId() > 2)       /*过滤id大于2的元素*/
    .forEach(System.out::println);     /*遍历输出*/

logger.warn("*********************获取指定数量的元素*********************");
all.stream()
    .filter(a -> a.geteId() > 5)     /*过滤*/
    .limit(2)                        /*收集的元素数量*/
    .forEach(System.out::println);

logger.warn("*********************跳过几个元素*********************");
all.stream().filter(a -> a.geteId() >2)     /*过滤*/
    .skip(2)                        /*过滤后,再跳过几个元素*/
    .forEach(System.out::println);

logger.warn("*********************去重*********************");
all.stream().distinct()     /*必须实现hashCode和,equals方法*/
    .forEach(System.out::println);
查找与匹配

image-20201130213936907

匹配

allMathch 检查是否匹配所有元素

image-20201130213948527

anyMatch 检查是否至少匹配一个元素

image-20201130213954095

noneMatch 检查是否没有匹配的元素

image-20201130213958617

查找

findFirst 返回第一个元素

image-20201130214006423

findAny 返回当前流中任意的元素

image-20201130214011282

count 返回流中元素总数

image-20201130214017038

max 返回流中最大值

image-20201130214022880

min 返回最小值

reduce归约

image-20201130214032000

image-20201130214037376

reduce(起式值,运算式)

image-20201130214044046

collect 收集 (重要)

image-20201130214051369

logger.warn("--------------获取用户数据集合--------------------");
List<Employee> all = mapper.findAll();
logger.warn("--------------将用户名收集到list集合中--------------------");
List<String> strings = all.stream()     /*将对象转换为流*/
    .map(e -> e.geteName())         /*将name属性提取到流中*/
    .collect(Collectors.toList());  /*将name属性收集进list集合中*/
logger.warn(strings);

logger.warn("--------------将用户名收集到set集合中--------------------");
Set<String> dateSet = all.stream()
    .map(Employee::geteName)       /*将name属性提取到流中*/
    .collect(Collectors.toSet());  /*将流中的属性保存进set集合中*/
logger.warn(dateSet);

logger.warn("--------------将用户名收集到HasSet集合中--------------------");
HashSet<String> hashSet = all.stream()
    .map(Employee::geteName)
    .collect(Collectors.toCollection(HashSet::new)); /*将流中对象收集进HasSet中*/
logger.warn(hashSet);

logger.warn("-----将用户Id,作为key,用户名作为value,收集到Map集合中,默认使用HasMap实例化---------");
Map<Integer, String> collect =
    all.stream().
    collect(Collectors.toMap(a -> a.geteId(),   /*将流中对象的id作为key*/
                             a -> a.geteName()));                /*将流中对象的name属性作为value收集进Map集合中*/
logger.warn(collect);

logger.warn("--------将用户Id,作为key,用户对象作为value,收集到Map集合中,默认使用HasMap实例化------");
Map<Integer, Employee> employeeMap =
    all.stream()
    .collect(Collectors.toMap(Employee::geteId,     /*将流中对象的id作为key*/
                              Function.identity()));              /*将流中对象作为value,收集进map集合中*/
logger.warn(employeeMap);

Collectors.toMap 有三个重载方法:

(1)toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);

(2)toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction);

(3)toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);

​ keyMapper:Key 的映射函数

​ valueMapper:Value 的映射函数

​ mergeFunction:当 Key 冲突时,调用的合并方法

​ mapSupplier:Map 构造器,在需要返回特定的 Map 时使用

示例:如果 List 中 userId 有相同的,使用上面的写法会抛异常:

List<User> userList = Lists.newArrayList(
        new User().setId("A").setName("张三"),
        new User().setId("A").setName("李四"), // Key 相同 
        new User().setId("C").setName("王五")
);

userList.stream().collect(Collectors.toMap(User::getId, User::getName));

// 异常:
java.lang.IllegalStateException: Duplicate key 张三 

// 这时就需要调用第二个重载方法,传入合并函数,如:
userList.stream().collect(Collectors.toMap(User::getId, User::getName, (n1, n2) -> n1 + n2));

/**
输出结果
A-> 张三李四 
C-> 王五
**/

// 第四个参数(mapSupplier)用于自定义返回 Map 类型,比如我们希望返回的 Map 是根据 Key 排序的,可以使用如下写法:

List<User> userList = Lists.newArrayList(
        new User().setId("B").setName("张三"),
        new User().setId("A").setName("李四"),
        new User().setId("C").setName("王五")
);

userList.stream().collect(
    Collectors.toMap(User::getId, User::getName, (n1, n2) -> n1, TreeMap::new)
);

/**
A-> 李四 
B-> 张三 
C-> 王五
**/
其他操作(重)
logger.warn("*************从数据库中获取员工数据*************");
List<Employee> all = mapper.findAll();

logger.warn("*************获取员工总数*************");
Long aLong = all.stream()   /* 将集合转换为stream流 */
   .collect(Collectors.counting());   /*从流中获取员工总数*/
logger.warn(aLong);

logger.warn("*************获取员工薪水的平均值*************");
Double aDouble = all.stream().
   collect(Collectors.averagingDouble(Employee::getSalary));   /*从流中获取薪水的平均值,注意:获取平均值必须为数值类型才可以*/
logger.warn(aDouble);

logger.warn("*************获取员工薪水的最大值,最小值等等*************");
DoubleSummaryStatistics statistics = all.stream()
   .collect(Collectors.summarizingDouble(Employee::getSalary));  
logger.warn(statistics);
//        输出的结果:DoubleSummaryStatistics{count=14, sum=66888.400000, min=4000.000000, average=4777.742857,max=7000.000000}

logger.warn("*************获取员工薪水进行分组*************");
Map<Double, List<Employee>> collect = all.stream()
   .collect(Collectors.groupingBy(Employee::getSalary));   /*从流中,根据员工薪水进行分组*/
collect.forEach((k, v) -> logger.warn("key=" + k + "  value=" + v));

// 输出结果
// *************获取员工总数*************
// 14
// *************获取员工薪水的平均值*************
// 4777.742857142856
// *************获取员工薪水总和*************
// DoubleSummaryStatistics{count=14, sum=66888.400000, min=4000.000000, average=4777.742857, max=7000.000000}
// *************获取员工薪水进行分组*************
// key=5888.4  value=[Employee{eId=14,eName='zs', postId=3, date=2020-11-19 08:00:00, salary=5888.4, mgrPid=null, departmentId=null}]
// key=5000.0  value=[Employee{eId=3,eName='ls', postId=2, date=2020-10-25 08:00:00, salary=5000.0, mgrPid=1, departmentId=2},
//                    Employee{eId=5, eName='zl', postId=2, date=2020-10-25 08:00:00, salary=5000.0, mgrPid=1, departmentId=4}]
// key=6000.0  value=[Employee{eId=8,eName='zs1', postId=3, date=2020-10-25 08:00:00, salary=6000.0, mgrPid=4, departmentId=3},
//                    Employee{eId=11, eName='zl1', postId=3, date=2020-10-25 08:00:00, salary=6000.0, mgrPid=3, departmentId=2}]
// key=7000.0  value=[Employee{eId=10,eName='ww1', postId=3, date=2020-10-25 08:00:00, salary=7000.0, mgrPid=2, departmentId=1}]
// key=4000.0  value=[Employee{eId=1,eName='zxm', postId=1, date=2020-10-25 08:00:00, salary=4000.0, mgrPid=null, departmentId=1},
//                   Employee{eId=2, eName='zs', postId=2, date=2020-10-25 08:00:00, salary=4000.0, mgrPid=1,departmentId=1}, 
//                   Employee{eId=4, eName='ww', postId=2, date=2020-10-25 08:00:00, salary=4000.0,mgrPid=1, departmentId=3}, 
//                   Employee{eId=6, eName='qq', postId=3, date=2020-10-25 08:00:00, salary=4000.0, mgrPid=2, departmentId=1}, 
//                   Employee{eId=7, eName='zb', postId=3, date=2020-10-25 08:00:00,salary=4000.0, mgrPid=3, departmentId=2}, 
//                   Employee{eId=9, eName='ls1', postId=3, date=2020-10-2508:00:00, salary=4000.0, mgrPid=5, departmentId=4}, 
//                   Employee{eId=12, eName='qq1', postId=3,date=2020-10-25 08:00:00, salary=4000.0, mgrPid=4, departmentId=3}, 
//                   Employee{eId=13, eName='zb1',postId=3, date=2020-10-25 08:00:00, salary=4000.0, mgrPid=5, departmentId=4}]

image-20201130214339203

image-20201130214345373

根据true,false分组

image-20201130214352426

获取对薪水的总数,平均数,等等

image-20201130214357529

连接

image-20201130214403537

3、终止操作

终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似
StringBuilder 那样的链式调 用。本小节中,终结方法包括 count 和 forEach 方法。

非终结方法:返回值类型仍然是 Stream
接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余
方法均为非终结方法。)

(四)反射机制

获取字节码Class对象

  1. Class.forName(“包点类名”);

  2. 实例对象名.getClass()方法

  3. Class类名.class属性

创建对象的方式。

  1. 使用反射无参:创建对象只需要一个类名创建Class对象然后通过Class对象的newInstance()方法创建目标对象
public class ServiceFactoy {
    public static IService  getIserviceimpl(String clsString) throws Exception {
        Class cls = Class.forName(clsString);
        Constructor ctr = cls.getConstructor();
        return (IService)ctr.newInstance();
    }
}
  1. 使用反射有参:使用Class对象的getConstuctor()方法拿到构造器(Constutor对象),然后通过构造器的newIntansce()方法实例化并初始化对象
public class DAOFactory {
    public static DAO<Student> StudentDAOimplFacotry(String claString,Connection conn) throws Exception {
        //		根据传入的目标对象的包。类名创建改对象的Class对象
        Class cls = Class.forName(claString);
        //		通过Class对象获取,目标对象的构造方法,并获得构造器对象
        Constructor cst = cls.getConstructor(Connection.class);
        //		通过构造器对象实例化目标对象
        return (DAO<Student>)cst.newInstance(conn);
    }
}

Class 类中方法详解

1、获取成员变量

  1. Field[] getFields() 获取public的所有成员变量

  2. Field getField(String name) 获取public的指定名称变量

  3. Field[] getDeclaredFields() 获取全部成员变量,不考虑修饰符

  4. Field getDeclaredField(string name )
    获取public的指定名称变量,不考虑修饰符

Filed成员对象方法

  • set(对象,属性值) 为指定的对象设置属性值

  • get()对象 获取指定对象的属性值

  • setAccessible(true); 可以访问私有的属性或者方法

2.获取构造方法

  1. Constructor<?>[] getConstructors() 获取public无参的构造器

  2. Constructor<T> getConstructor(Class<?>… parameterTypes)
    获取public有参的构造器,需要传递对应参数的Class对象,

如:String则要传递String.class

  1. Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes)
    获取有参的构造器,不考虑修饰符,需要传递对应参数的Class对象,

  2. Constructor<?>[] getDeclaredConstructors()
    获取无参的构造器,不考虑修饰符

Constructor构造器对象方法

  1. newInstance(obj… 参数);
    构造方法有参数则传递对应类型的参数,没有参数则不用传参,返回该类对象

3.获取成员方法们:

  1. Method[] getMethods() 获取所有的public方法

  2. Method getMethod(string name, Class<?>… parameterTypes)

参数:方法名,参数列表的Class对象,获取指定名称,和指定参数列表的方法

  1. Method[] getDeclaredMethods()

  2. Method getDeclaredMethod(String name,Class<?>… parameterTypes)

Method方法对象:方法

  • invoke(对象,args)
    调用方法,有参数需要传递指定的参数类型并需要传递调用此方法的对象

  • getName() 获取方法名

注解:@注解名称

JDK中预定义的一些注解

  1. @Override :检测被该注解标注的方法是否是继承自父类(接口)的

  2. @Deprecated:该注解标注的内容,表示已过时

  3. @SuppressWarnings:压制警告

自定义注解

格式:public @interface 注解名称{}

  1. 本质:注解本质上就是一个接口,该接口默认继承Annotation接口

public interface 自定义注解类 extends Annotation {}

  1. 属性:接口中的抽象方法

  2. .属性的返回值类型有下列取值:基本数据类型,string,枚举,注解,以上类型的数组

  3. 定义了属性,在使用时需要给属性赋值

    • 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。

    • 如果只有一个属性需要赋值,例如:属性的名称是value,则value可以省略,
      直接定义值即可

    • 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{ }省略

  4. 元注解

元注解:用于描述注解的注解

  1. @Target:描述注解能够作用的位置

El ementType取值:

  1. TYPE :可以作用于类上

  2. METHOD:可以作用于方法上

  3. FIELD :可以作用于成员变量上

  4. @Retention:描述注解被保留的阶段、

    1. @Retention( RetentionPolicy . RUNTIME)
      :当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
  5. @Documented: 描述注解是否被抽取到api文档中

  6. @Inherited: 描述注解是否被子类继承

解析注解

image-20201130214529387

项目实战(DAO => 基于Oracle)

学员编号 int primary key

班级 varchar2(10) not null

学员姓名 varchar2(10)

性别 varchar2(4) check(“男” and “女”)

年龄 int check (>0 < 50)

出生日期 date

家庭住址 varchar2(40)

1、创建数据库表 设置主键

create table student(
    stu_bh int primary key,
    stu_bj varchar2(10) not null,
    stu_name varchar2(20) not null,
    stu_sex varchar2(4) check(stu_sex = '男' or stu_sex = '女'),
    stu_nl int check(stu_nl \> 0 and stu_nl \< 50),
    stu_date varchar2(30),
    stu_jt varchar2(50)
);

2、创建序列自增

create sequence user_Sequence
  increment by 1 -- 每次加几个 
  START WITH 1 -- 从1开始计数 
  NOMAXVALUE -- 不设置最大值 
  NOCYCLE -- 一直累加,不循环 
  CACHE 100; 

create sequence stu_seq
increment by 1
START WITH 1
NOMAXVALUE
NOCYCLE
CACHE 100; 

附 删除序列: DROP SEQUENCE user_Sequence

3、实际开发中创建触发器实现自增! 创建触发器

create or replace trigger 触发器名      
before insert on 表名  	/*触发条件:当向表dectuser执行插入操作时触发此触发器*/    
 for each row    		 /*对每一行都检测是否触发*/    
begin   			/*触发器开始*/    
select  序列名.nextval into :new.列名 from dual;   	/*触发器主题内容,即触发后执行的动作,*/
end; 					/*在此是取得序列dectuser_tb_seq的下一个*/
/					/*值插入到表dectuser中的userid字段中*/    


create or replace trigger stu_trigger
before insert on student
for each row 
begin
select  stu_seq.nextval into :new.stu_bh from dual;
end; 
/

附 删除触发器:drop trigger users_trigger;

4、测试数据

insert into student values(1,'x1809','张三','男',20,'1997-12-13','湖北荆州');

insert into student(stu_bj,stu_name,stu_sex,stu_nl,stu_date,stu_jt)
values('x1809','李四','男',20,'1997-12-13','湖北荆州')

5、创建JDBC连接

public class DatabaseConnection {
	private static String USERNAMR = "scott";
	private static String PASSWORD = "tiger";
	private static String DRVIER = "oracle.jdbc.OracleDriver";
	private static String URL = "jdbc:oracle:thin:@localhost:1521:orcl";
	private Connection conn = null;
	
	public DatabaseConnection() {
		
		try {
			  Class.forName(DRVIER);
              this.conn = DriverManager.getConnection(URL, USERNAMR, PASSWORD);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("連接成功:"+conn);
	}
	
	public Connection getConn() {
		return this.conn;
	}
	
	public void close() {
		try {
			if(this.conn!=null) {
				this.conn.close();
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

5.1、创建Student学生类(VO)

public class Student implements Serializable {
	private Integer stu_bh;
	private String stu_bj;
	private String stu_name;
	private String stu_sex;
	private Integer stu_nl;
	private String stu_date;
	private String stu_jt;
/***
*实现属性的seter和geter方法
*/
}

6、实现数据层接口(DAO)

public interface DAO<T> {
	/***
	 * 新增數據
	 * @return	新增是否成功,成功返回true
	 * @throws Exception
	 */
	public boolean Insert(T t)throws Exception;
	/***
	 * 刪除數據
	 * @return	刪除成功返回true
	 * @throws Exception
	 */
	public boolean Delete(Integer[] ids)throws Exception;
	/***
	 * 數據更新
	 * @return 更新成功返回true
	 * @throws Exception
	 */
	public boolean Update(T t)throws Exception;
	/***
	 * 查詢全部
	 * @return	返回查詢數據
	 * @throws Exception
	 */
	public List<T> fildAll()throws Exception;
	/***
	 * 根據Id查詢數據
	 * @param id
	 * @return	
	 * @throws Exception
	 */
	public T fildId(Integer id)throws Exception;
	/***
	 * 登陸驗證
	 * @param user
	 * @param pass
	 * @return	登陸成功返回true
	 * @throws Exception
	 */
	public boolean Login(String user,String pass)throws Exception;	
	/***
	 * 條件查詢,根據條件與值進行查詢
	 * @param v1	條件
	 * @param v2	值
	 * @return
	 * @throws Exception
	 */
	public List<T> fildS(String v1,String v2)throws Exception;
}

7、实现数据层(DAOimpl)

/***
 * 数据层主要用于处理原子操作,对数据库进行操作
 * @author ssa
 *
 */
public class StudentDAOimpl implements IDAO<Student> {

	private Connection conn = null;
	
	/***
	 * 在构造方法中获取连接对象
	 * @param conn
	 */
	public StudentDAOimpl(Connection conn) {
		this.conn = conn;
	}
	
	/***
	 * 添加数据
	 */
	@Override
	public boolean Insert(Student t) throws Exception {
		try {
			String sql = "insert into student values(?,?,?,?,?,?,?)";
			PreparedStatement premt = conn.prepareStatement(sql);
			premt.setString(1, t.getStu_bh().toString());
			premt.setString(2, t.getStu_bj().toString());
			premt.setString(3, t.getStu_name());
			premt.setString(4, t.getStu_sex());
			premt.setString(5, t.getStu_nl().toString());
			premt.setString(6, t.getStu_date().toString());
			premt.setString(7, t.getStu_jt());
			return premt.executeUpdate()>0;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/***
	 * 删除数据
	 */
	@Override
	public boolean Delete(Integer[] ids) throws Exception {
		
		try {
			StringBuffer sBuffer = new StringBuffer("Delete student where stu_bh in(");
			for(int i = 0 ; i < ids.length ; i++ ) {
				sBuffer.append(ids[i]).append(",");
			}
			sBuffer.delete(sBuffer.length()-1, sBuffer.length()).append(")");
			PreparedStatement parmet = conn.prepareStatement(sBuffer.toString());
			return parmet.executeUpdate()>0;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/***
	 * 更新数据
	 */
	@Override
	public boolean Update(Student t) throws Exception {
		try {
			String sql = "update student set stu_bj = ? ,stu_name=?,stu_sex = ?,stu_nl = ?,stu_date = ?,stu_jt = ? where stu_bh = ?";
			PreparedStatement premt = conn.prepareStatement(sql);
			premt.setString(1, t.getStu_bj().toString());
			premt.setString(2, t.getStu_name());
			premt.setString(3, t.getStu_sex());
			premt.setString(4, t.getStu_nl().toString());
			premt.setString(5, t.getStu_date().toString());
			premt.setString(6, t.getStu_jt());
			premt.setInt(7, t.getStu_bh());
			return premt.executeUpdate()>0;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/***
	 * 查询全部数据
	 */
	@Override
	public List<Student> fildAll() throws Exception {
		List<Student> all = new ArrayList<Student>();
		Student stu = null;
		try {
			String sql = "select * from student";
			PreparedStatement parmet = conn.prepareStatement(sql);
			ResultSet rSet = parmet.executeQuery();
			while (rSet.next()) {
				stu = new Student();
				stu.setStu_bh(rSet.getInt(1));
				stu.setStu_bj(rSet.getString(2));
				stu.setStu_name(rSet.getString(3));
				stu.setStu_sex(rSet.getString(4));
				stu.setStu_nl(rSet.getInt(5));
				stu.setStu_date(rSet.getString(6));
				stu.setStu_bj(rSet.getString(7));
				all.add(stu);
			}
			return all;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/***
	 * 根据id进行查询
	 */
	@Override
	public Student fildId(Integer id) throws Exception {
		Student stu = null;
		try {
			String sql = "select * from student where stu_bh = ?";
			PreparedStatement parmet = conn.prepareStatement(sql);
			parmet.setInt(1, id);
			ResultSet rSet = parmet.executeQuery();
			while (rSet.next()) {
				stu = new Student();
				stu.setStu_bh(rSet.getInt(1));
				stu.setStu_bj(rSet.getString(2));
				stu.setStu_name(rSet.getString(3));
				stu.setStu_sex(rSet.getString(4));
				stu.setStu_nl(rSet.getInt(5));
				stu.setStu_date(rSet.getString(6));
				stu.setStu_bj(rSet.getString(7));
			}
			return stu;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/***
	 * 条件查询
	 */
	@Override
	public List<Student> fildS(String v1, String v2) throws Exception {
		List<Student> all = new ArrayList<Student>();
		Student stu = null;
		try {
			String sql = "select * from student where ? = ?";
			PreparedStatement parmet = conn.prepareStatement(sql);
			parmet.setString(1, v1);
			parmet.setString(1, v2);
			ResultSet rSet = parmet.executeQuery();
			while (rSet.next()) {
				stu = new Student();
				stu.setStu_bh(rSet.getInt(1));
				stu.setStu_bj(rSet.getString(2));
				stu.setStu_name(rSet.getString(3));
				stu.setStu_sex(rSet.getString(4));
				stu.setStu_nl(rSet.getInt(5));
				stu.setStu_date(rSet.getString(6));
				stu.setStu_bj(rSet.getString(7));
			}
			return all;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

7.1、实现数据层工厂类(DAOFactoy)

public class DAOFactory {
	public static DAO<Student> StudentDAOimplFacotry(String claString,Connection conn) throws Exception {
//		根据传入的目标对象的包。类名创建改对象的Class对象
		Class cls = Class.forName(claString);
//		通过Class对象获取,目标对象的构造方法,并获得构造器对象
		Constructor cst = cls.getConstructor(Connection.class);
//		通过构造器对象实例化目标对象
		return (DAO<Student>)cst.newInstance(conn);
	}
}

8、实现业务层(Service)

/***
 * 业务层主要用来调用数据层的处理逻辑
 * @author ssa
 *
 */
public class StudentServiceimpl implements IService<Student> {
	private DatabaseConnection dbc = new DatabaseConnection();
	private String claString = "cn.mldn.lxh.dao.impl.StudentDAOimpl";
	
	public StudentServiceimpl() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean Add(Student t) throws Exception {
		try {
			if(DAOFactory.getDAOimpl(claString, dbc.getConn()).fildId(t.getStu_bh())==null) {
				return DAOFactory.getDAOimpl(claString, dbc.getConn()).Insert(t);
			}
			System.out.println("也存在ID为:"+t.getStu_bh());
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			dbc.close();
		}
		return false;
	}

	@Override
	public boolean Remove(Integer[] ids) throws Exception {
		try {
			return DAOFactory.getDAOimpl(claString, dbc.getConn()).Delete(ids);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			dbc.close();
		}
		return false;
	}

	@Override
	public boolean Replace(Student t) throws Exception {
		try {
			if(DAOFactory.getDAOimpl(claString, dbc.getConn()).fildId(t.getStu_bh())!=null) {
				return DAOFactory.getDAOimpl(claString, dbc.getConn()).Update(t);
			}
			System.out.println("不存在ID为:"+t.getStu_bh());
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			dbc.close();
		}
		return false;
	}

	@Override
	public List<Student> SelectAll() throws Exception {
		try {
			return DAOFactory.getDAOimpl(claString, dbc.getConn()).fildAll();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			dbc.close();
		}
		return null;
	}

	@Override
	public Student SelectId(Integer id) throws Exception {
		try {
			if(DAOFactory.getDAOimpl(claString, dbc.getConn()).fildId(id)!=null) {
				return (Student)DAOFactory.getDAOimpl(claString, dbc.getConn()).fildId(id);
			}
			System.out.println("不存在ID为:"+id);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			dbc.close();
		}
		return null;
	}

	@Override
	public boolean Login(String user, String pass) throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public List<Student> SelectS(String v1, String v2) throws Exception {
		try {
			if(v1!=null&&v2!=null) {
				return DAOFactory.getDAOimpl(claString, dbc.getConn()).fildS(v1, v2);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			dbc.close();
		}
		return null;
	}
}

8.1、实现业务层工厂类(ServiceFactory)

public class ServiceFactoy {
	public static IService  getIserviceimpl(String clsString) throws Exception {
		Class cls = Class.forName(clsString);
		Constructor ctr = cls.getConstructor();
		return (IService)ctr.newInstance();
	}
}

9、Oracle分页参考

分页查询
参考
select * from  ( select rownum rn, e.* from  ( select * from EMP) e )   where rn > pageSize * (page - 1) and rn <= pageSize * page

select * from ( select rownum rn, e.* from ( select * from EMP) e )where rn > 9 * (page - 1) and rn <= 9 * page
注意:
pageSize:表示每页最大显示数量
page:表示显示第几页、

分析源码:
我们选定每页(pageSize)为5。那么EMP表目前共有三页,1~5行为1页;6~10行为1页;1~15行为1页(缺第15行,那么第3页就显示4行记录)
页面从第1页开始。
我们要查询第2页的记录,那么page = 2。
那么第2页是由第6,7,8,9,10行记录形成的。

ete(ids);
} catch (Exception e) {
e.printStackTrace();
}finally {
dbc.close();
}
return false;
}

@Override
public boolean Replace(Student t) throws Exception {
	try {
		if(DAOFactory.getDAOimpl(claString, dbc.getConn()).fildId(t.getStu_bh())!=null) {
			return DAOFactory.getDAOimpl(claString, dbc.getConn()).Update(t);
		}
		System.out.println("不存在ID为:"+t.getStu_bh());
	} catch (Exception e) {
		e.printStackTrace();
	}finally {
		dbc.close();
	}
	return false;
}

@Override
public List<Student> SelectAll() throws Exception {
	try {
		return DAOFactory.getDAOimpl(claString, dbc.getConn()).fildAll();
	} catch (Exception e) {
		e.printStackTrace();
	}finally {
		dbc.close();
	}
	return null;
}

@Override
public Student SelectId(Integer id) throws Exception {
	try {
		if(DAOFactory.getDAOimpl(claString, dbc.getConn()).fildId(id)!=null) {
			return (Student)DAOFactory.getDAOimpl(claString, dbc.getConn()).fildId(id);
		}
		System.out.println("不存在ID为:"+id);
	} catch (Exception e) {
		e.printStackTrace();
	}finally {
		dbc.close();
	}
	return null;
}

@Override
public boolean Login(String user, String pass) throws Exception {
	// TODO Auto-generated method stub
	return false;
}

@Override
public List<Student> SelectS(String v1, String v2) throws Exception {
	try {
		if(v1!=null&&v2!=null) {
			return DAOFactory.getDAOimpl(claString, dbc.getConn()).fildS(v1, v2);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}finally {
		dbc.close();
	}
	return null;
}

}





## 8.1、实现业务层工厂类(ServiceFactory)

```java
public class ServiceFactoy {
	public static IService  getIserviceimpl(String clsString) throws Exception {
		Class cls = Class.forName(clsString);
		Constructor ctr = cls.getConstructor();
		return (IService)ctr.newInstance();
	}
}

9、Oracle分页参考

分页查询
参考
select * from  ( select rownum rn, e.* from  ( select * from EMP) e )   where rn > pageSize * (page - 1) and rn <= pageSize * page

select * from ( select rownum rn, e.* from ( select * from EMP) e )where rn > 9 * (page - 1) and rn <= 9 * page
注意:
pageSize:表示每页最大显示数量
page:表示显示第几页、

分析源码:
我们选定每页(pageSize)为5。那么EMP表目前共有三页,1~5行为1页;6~10行为1页;1~15行为1页(缺第15行,那么第3页就显示4行记录)
页面从第1页开始。
我们要查询第2页的记录,那么page = 2。
那么第2页是由第6,7,8,9,10行记录形成的。
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值