java se基础知识

来源:互联网 发布:mac如何卸载app 编辑:程序博客网 时间:2024/06/06 09:33
《Java》
环境变量

新建 JAVA_HOME C:\Program Files (x86)\Java\jdk1.8.0_31
一般存在,添加 Path ;%JAVA_HOME%\bin
不存在就新建 classpath .;%JAVA_HOME%\lib;

命令行运行Java代码
D:\Test.java
public class Test {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
C:\Users\bonld_000>cd..

C:\Users>cd..

C:\>D:

D:\>javac Test.java

D:\>java Test
Hello Java

D:\>
MyEclipse字体修改

Windows -> Perferences -> 左上角搜索”font”
Java代码字体:


控制台字体:



输入输出
快速代码:
// 打“main”按Alt+?组合件,点击Enter
public static void main(String[] args)
// 打“syso”按Alt+?组合件,点击Enter
System.out.println("请输入用户名:");
// 自动生辰返回值:ctrl+1 -> 选择“.... new local variable”(新本地变量)
String _s = _sc.nextLine();



import java.util.Scanner;

public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String nextLine = sc.nextLine();
System.out.println("您输入的是:" + nextLine);
System.out.printf("您输入的是:%s", nextLine); // C语言风格输出
sc.close();
}
}

Java注释
第一种注释://单行
第二种注释:/* 多行注释 */
第三种注释:/**+回车键
/**
* Javadoc类型的注释
* @param args
*/
Eclipse中注释的快捷键:Ctrl+?
变量
标识符由A-Z,a-z,0-9,_,$(中文)
0-9不能打头
命名要求:见名知意
变量命名规范:
 Java的命名一般遵循“驼峰标识”:每个单词首字母大写,另外——
 类:首字符大写
 变量:首字母小写
 函数(方法):首字母小写

int $n=1;
Java 8 VS2012(C#.Net Framework 4.5) Dev C++(5.11@2015)
OK Err OK


结构化编程
选择结构
三目运算符
static int getMax(int x, int y){
// if (x >= y){
// return x;
// }else{
// return y;
// }
return (x >= y)?x:y;
}


switch (day) {
case 1:
System.out.println("月曜日");
break;
case 2:
System.out.println("火曜日");
break;
default:
System.out.println("何曜日?");
break;
}
支持字符串
break可以省略,省略的后果是代码继续走下一个case,直到遇到break,一定要注意,不能漏了break
循环结构
 While循环:先判断
 死循环:while(true){...}
 Do...while循环:后判断,最后要加分号”;”
 For循环:简化变量管理
 死循环:for(;;){...}

 退出循环
 break; 退出当前循环
 Continue; 结束本次循环,继续下次循环
 Return; 退出函数,不推荐

运算符
位运算符
重点掌握:
>> 右移(除以2n)
<< 左移(乘以2n)
一般了解:
& 位与(相当于AND)
| 位或(相当于OR)
^ 亦或(叛逆,同0异1)
数组
数组的定义
C语言风格
int a[] = { 1, 2, 3, 4, 5, 6 };

Java风格(面向对象风格)
int[] b = { 5, 6, 7, 8 };

可以不赋初始值(但要指定长度)
int[] c = new int[5];

遍历数组
int[] c = new int[5];

// 写入
for (int i = 0; i < c.length; i++) {
c[i] = i*2;
}

// 输出
for (int i = 0; i < c.length; i++) {
System.out.println(c[i]);
}
// foreach循环遍历数组:只读
for(int n : c){
System.out.println(n);
}

冒泡排序


一个数和其它数比较(循环)
每个数都要做这种比较(再一层循环)
冒泡排序三步走:
循环
交换
回一手(减少比较次数,提高效率)
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
int temp;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] < arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int n : arr) {
System.out.println(n);
}
}


二维数组
int arrC[][] = new int[2][3];
int[][] arrJ = new int[2][3];
int[][] arrJ2 = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

例:表格数据输出
霸王别姬 阿甘正传 大话西游
Andy 9.5 9.4 9.1
Bob 3 8.7 9
Cat 3 7 1
Dog 9.9 3 3
public static void main(String[] args) {

double[][] films = {
{ 9.5, 9.4, 9.1 },
{ 3, 8.7, 9 },
{ 3, 7, 1 },
{ 9.9, 3, 3 }
};

// 二维数组的遍历
for (int i = 0; i < films.length; i++) {
for (double n : films[i]) {
System.out.print(n + " ");
}
System.out.println();
}
}


题:判断一个3*3的矩阵是不是单位矩阵“Unit Matrix”(对角线上元素是1,其余元素是0)
1 0 0
0 1 0
0 0 1

int[][] m = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};

for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
if ((i == j && m[i][j] == 1)) {
// 1.对角线上元素是1
} else if (i != j && m[i][j] == 0) {
// 2.非对角线上元素是0
} else {
// 3.以上都不满足
System.out.println("不是單位矩陣");
return;
}
}
}

System.out.println("是单位矩阵");

题:矩阵乘法:
设A为m*p的矩阵
B为p*n的矩阵
那么称m*n的矩阵C为矩阵A与B的乘积
记作C=AB
矩阵C中的第i行第j列元素可以表示为:




字符串
长度 s.length()
大小写转换 s.toUpperCase() s.toLowerCase()

去空格 s.trim()
右对齐 String.format("%10s", s)
左对齐 String.format("%-10s", s);
时间转字符串 Date d = new Date();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String sDate = f.format(d);

包含查询 s.contains("晁盖")
子字符串 s.substring(1)
String substring2 = s.substring(3, 3 + 3)
下标查询 s.indexOf("阳跻") :查不到返回-1
s.lastIndexOf("阳跻")

叛空 if (s2 == null || s2.isEmpty())
字符串比较 if ("字符串写左边".equals(变量写右边))

StringBuilder StringBuilder sb = new StringBuilder();
sb.append("诸");
sb.append("葛");
sb.append("孔");
sb.append("明");
System.out.println(sb.toString());
StringBuffer 安全,但效率较低

例:String sFile = "D:\\迅雷下载\\新建文件\\[陈奕迅]喜欢一个人_bd.mp4";
1.求文件名
2.求后缀名
int _最后斜杠的下标 = sFile.lastIndexOf("\\");
int _后缀名的位置 = sFile.lastIndexOf(".");
String _文件名= sFile.substring(_最后斜杠的下标 + 1, _后缀名的位置);
String _后缀名 = sFile.substring(_后缀名的位置);
System.out.println(_文件名);
System.out.println(_后缀名);

类和对象
类是对对象的描述,是创建对象的“模板”,是对象的抽象。
对象是类的一个实例,是类的实例化结果。

类 对象
Scanner sc =new Scanner(System.in)
String s1 = "";
s2 = new String();
s3 = new String();

装箱·拆箱

int a1 = 1000;
装箱 Integer objA =a1;
拆箱 int a2 = objA;

封装
访问修饰符
private(类自己可以用)→default(不加修饰符,包内可用)→protected→public(谁都可以用)

*public:谁都可以使用
*protected:子类可以使用
*private:只有自己可以式样

属性
1.成员变量设为private
2.提供public的get/set方法作为访问器
自动生成属性快捷键

// 私有成员变量
private String who;

// 公共访问器:getter
public String getWho() {
return who;
}

// 公共访问器:setter
public void setWho(String who) {
this.who = who;
}

方法
局部变量·成员变量
成员变量:类里面定义的变量
局部变量:方法中定义的变量;复合语句中定义的变量for(int n : arr){...}
递归
1.阶乘
static int factorial(int n) {
if (n == 0) {
// 0! = 1
return 1;
} else {
// n ≠ 0,n! = n*(n-1)!
return n * factorial(n - 1);
}
}

2.兔子数列
static int rabbit(int m){
// 1月:1
// 2月:1
// 3月:1月+2月
// ...
// m月:(m-1)月+(m-2)月
if (m==1 || m==2){
return 1;
}else{
return rabbit(m-1)+rabbit(m-2);
}
}

构造方法
特点:1.没有返回值;2.方法名必须和类名一致。
无参构造方法:
1.如果不手写一个,系统默认提供一个。new 类():实际上是调用类的构造方法。
2.如果手写带参构造方法,系统不再提供无参构造方法。可以再手写一个无参构造方法。
构造方法的主要作用:初始化对象——为成员变量赋初始值

MyEclipse中构造方法自动生成:


重载
1.方法名相同
2.参数列表不同:
a) 参数类型相同,个数不同
b) 参数个数相同,类型不同
3.重载不管返回类型
静态
静态方法
不需要new(实例化对象)就可以使用的方法。
使用方式:类名.静态方法名(参数列表);
如果是在当前类中调用,类名可以省略。
public class D0503静态 {

// 静态方法
public static void main(String[] args) {
D0503静态.method静态方法();// 本类中,通过类名调用
method静态方法();// 本类中,也可以直接调用

Dog.method静态方法();// 其他类中,“必须”通过类名调用

Dog _dog = new Dog();
_dog.method普通方法();// 非静态方法(普通方法),必须实例化对象(new),通过对象调用
}

void method普通方法() {
System.out.println("D0503静态.java method普通方法");
}

static void method静态方法() {
System.out.println("D0503静态.java method静态方法");
}
}

静态变量


静态代码块
普通代码块:类被创建(new)的时候执行,比构造方法还早。
静态代码块:类被使用的时候执行,比普通代码块还早。
继承
关键字:子类 extends 父类
this和super
this 自己的
super 父类的
super():父类构造方法
super.XXX:父类的成员(方法或变量)
再论构造方法
 无论子类构造方法带不带参数,默认都是执行父类的无参构造方法。【隐藏一句代码:super()】
 如果非要执行父类带参构造方法的话,使用super(参数列表)
练习:JD商品
public class JD商品 {
private int 价格;
private String 品牌;

public int get价格() {
return 价格;
}
public void set价格(int 价格) {
this.价格 = 价格;
}
public String get品牌() {
return 品牌;
}
public void set品牌(String 品牌) {
this.品牌 = 品牌;
}

}
public class JD手机 extends JD商品 {

private String 质保期;
//-----------------------------------

public String get质保期() {
return 质保期;
}
public void set质保期(String 质保期) {
this.质保期 = 质保期;
}

} public class JD饮料 extends JD商品 {

private String 保质期;
//-----------------------------------

public void set保质期(String 保质期) {
this.保质期 = 保质期;
}

public String get保质期() {
return 保质期;
}
}
public class D0601继承 {
public static void main(String[] args) {
JD手机 _m = new JD手机();
_m.set品牌("诺基亚");
_m.set价格(199);
System.out.println(_m.get品牌());
System.out.println(_m.get价格());
}
}

重写
子类重新定义继承自父类的方法。

final(不准修改)
 Final修饰类:该类不可被继承(比如String类)
 Final修饰方法:该方法不能被重写
 Final修饰变量:不能被重新赋值
Java的“常量”
public static final int CHANG_LIANG = 10;
多态
父类对象指向子类实例;父类对象调用(多种)子类方法
底层技术:后期绑定(根据运行时期对象实例来动态判断要调用的函数)
Car a;
a = new 大黄蜂();
a.running();

a = new 御天敌();
//---此处略去3000行代码
a.running();

接口
 接口定义”做什么”---接口中,方法没有具体实现(没有{...})
 实现类定义”具体怎么做”---在实现类中,该方法必须被重写
public interface D0702洪七公 {
public void 降龙十八掌();
}
Java 只允许单继承,使用接口可以实现多重继承
public class D0702郭靖 extends D0702郭啸天 implements D0702洪七公, D0702江南七怪 {


@Override
public void 双枪() {
System.out.println("没学");
}

@Override
public void 降龙十八掌() {
System.out.println("郭靖版 降龙十八掌");
}

@Override
public void 基本功() {
System.out.println("基本功");
}
}

抽象类
含有抽象方法的类,必须声明为抽象类abstract
抽象类也是类,不能同时继承多个抽象类

接口继承接口
抽象类继承抽象类
接口没有构造方法
抽象类有构造方法
抽象类不能被实例化

集合和泛型
导包:import java.util.*;
ArrayList
Boy _Pan = new Boy();

Girl _g1 = new Girl();
Girl _g2 = new Girl();
Girl _g3 = new Girl();

List _泰国五日游 = new ArrayList();
_泰国五日游.add(_g1);
_泰国五日游.add(_g2);
_泰国五日游.add(_g3);
_泰国五日游.add(_Pan);

for (int i = 0; i < _泰国五日游.size(); i++) {
Girl g = (Girl)_泰国五日游.get(i);
}
代码没错,运行出错(对象本是Boy类型,偏要转成Girl类型---类型转换异常)
Exception in thread "main" java.lang.ClassCastException


ArrayList<E>使用泛型:指定列表内元素的类型
List<Girl> _泰国五日游 = new ArrayList<>();
_泰国五日游.add(_g1);
_泰国五日游.add(_g2);
_泰国五日游.add(_g3);
//提示代码有错误:_泰国五日游.add(_Pan);

Vector和ArrayList用法一致
元素超过它的初始大小 线程安全 效率
ArrayList *150% × 高
Vector *200% √ 低


LinkedList
addFirst() 头部添加
addLast() 尾部添加
removeFirst()
removeLast()

HashSet
Set<String> s = new HashSet<>();
s.add("A");
s.add("B");
s.add("C");
s.add("D");
boolean b是否为空 = s.isEmpty();
boolean b是否包含 = s.contains("A");
boolean b移除結果 = s.remove("A");
// foreach:遍历set
for (String str : s) {
System.out.println(str);
}
// 迭代器:遍历set
Iterator<String> it = s.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println("Iterator : " + str);
}


HashMap
存储K-V使用的是:key来区分
添加K-V对:put
删除:remove(Key)
查询:
1.containsKey
2.containsValue
遍历map
for (String _key : m.keySet()) {
System.out.println("key = " + _key);
System.out.println(" value = " + m.get(_key));
}
使用迭代器迭代map
Collection<String> values = m.values();
// 获得迭代器
Iterator<String> it = values.iterator();
while(it.hasNext()){
String next = it.next();
System.out.println(next);
}



HashTable(不接受null)
*不接受
*不提示
*运行时出错
// X m.put(null, "NNN");
// X m.put("NNN", null);


顺序 重复
List √ √
Set 输出有序(无序) 覆盖
Map 输出有序
(无序) key不重复(覆盖)

自定义泛型
class AH<E> {
E x;
}
<?>通配符
什么泛型都接收
import java.util.*;

public class D0803自定义泛型 {

public static void main(String[] args) {
List<String> lst1 = new ArrayList<>();
lst1.add("A");
lst1.add("B");
lst1.add("C");
printList(lst1);


List<Integer> lst2 = new ArrayList<>();
lst2.add(1);
lst2.add(2);
lst2.add(3);
printList(lst2);
}

// <?> : 通配符
static void printList(List<?> lst2){
for (Object integer : lst2) {
System.out.println(integer);
}
}
}
*<? extends/super Person>
?表示只有继承自Person的类型是合法类型
<? extends Person>:定义参数
<? super Person>:定义变量/返回类型
import java.util.*;

public class D0803自定义泛型 {

public static void main(String[] args) {
List<Boy> lst1 = new ArrayList<>();
printList(lst1);

List<Girl> lst2 = new ArrayList<>();
printList(lst2);

List<String> lst3 = new ArrayList<>();
//String 没有继承Person,代码报错 printList(lst3);

List<? super Person> lst = new ArrayList<>();
lst.add(new Boy());
lst.add(new Girl());
//String 没有继承Person,代码报错 lst.add("A");
}

// <?> : 通配符
static void printList(List<? extends Person> lst2){
for (Object integer : lst2) {
System.out.println(integer);
}
}
}

class Person{
}
class Boy extends Person{
}

class Girl extends Person {
}

扩展:集合排序

package ah.day09;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class 集合扩展 {

// 1.调用Collections.sort(lst);
// 2.要排序的类型,必须implements Comparable<自身类型>
// 3.实现方法:compareTo() return 正(升序)/负(降序)
public static void main(String[] args) {
Phone p = new Phone(2299, 57000);
List<Phone> lst = new ArrayList<Phone>();
lst.add(p);

p = new Phone(1099, 260000);
lst.add(p);

p = new Phone(1299, 380000);
lst.add(p);

// Collection
Collections.sort(lst);

for (Phone ph : lst) {
System.out.println("价格:" + ph.getPrice() + " --- 销量:"
+ ph.getCount());
}
}
}

// -----------------------------------------
class Phone implements Comparable<Phone> {
private double price;
private int count;

public double getPrice() {
return price;
}

public int getCount() {
return count;
}

public Phone(double price, int count) {
super();
this.price = price;
this.count = count;
}

@Override
public int compareTo(Phone o) {
// this VS o(other)
if (this.price > o.price) {
// 返回正数:升序
return 10;
} else {
// 返回负数:降序
return -10000000;
}
}
}

多种方式排序
 Collections.sort(參數1:列表 參數2:比較器)
 定义比较器类:implements Comparator<Phone>
package ah.day09;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class 集合扩展 {

// 1.调用Collections.sort(lst);
// 2.要排序的类型,必须implements Comparable<自身类型>
// 3.实现方法:compareTo() return 正(升序)/负(降序)
public static void main(String[] args) {
Phone p = new Phone(2299, 57000);

List<Phone> lst = new ArrayList<Phone>();
lst.add(p);

p = new Phone(1099, 260000);
lst.add(p);

p = new Phone(1299, 380000);
lst.add(p);

// Collection
Collections.sort(lst);

for (Phone ph : lst) {
System.out.println("价格:" + ph.getPrice() + " --- 销量:"
+ ph.getCount());
}
System.out.println("-----------------銷量降序排列---------------");
// 按銷量降序(參數1:列表 參數2:比較器)
Collections.sort(lst, new CountDesc());
for (Phone ph : lst) {
System.out.println("价格:" + ph.getPrice() + " --- 销量:"
+ ph.getCount());
}
}
}

// -----------------------------------------
class Phone implements Comparable<Phone> {
private double price;
private int count;

public double getPrice() {
return price;
}

public int getCount() {
return count;
}

public Phone(double price, int count) {
super();
this.price = price;
this.count = count;
}

@Override
public int compareTo(Phone o) {
// this VS o(other)
if (this.price > o.price) {
// 返回正数:升序
return 10;
} else {
// 返回负数:降序
return -10000000;
}
}
}

// --------------
class CountDesc implements Comparator<Phone> {

@Override
public int compare(Phone o1, Phone o2) {
return (o1.getCount() > o2.getCount()) ? -1 : 1;
}
}

常用包
java.lang

包装类

原始数据类型 包装类
boolean(布尔型) Boolean
byte(字节型) Byte
char(字符型) Character
short(短整型) Short
int(整型) Integer
long(长整型) Long
float(浮点型) Float
double(双精度浮点型) Double

Math
Math.random()
java.util
Random

Random r = new Random();
for(int i = 0;i<10;i++){
System.out.println(r.nextInt(101));//0-100的随机整数
}


Date
Date d = new Date(1,6,1);
Calendar
// Calendar是抽象类,不能new
Calendar c = Calendar.getInstance();
// 精确添加添加(年,月,日)
c.add(Calendar.DATE, 49);// 49天之后的日期

// 获取年月日信息(月从0开始)
int i = c.get(Calendar.YEAR);
System.out.println(i);

// 设置具体日期(new Date(int year, int month, int date)的替代物)
c.set(2017, 8,1);

// 转成Date
Date time = c.getTime();
System.out.println(time);


异常
Try{尝试执行}
Catch{出错时执行}
Finally{出不出错都执行,在return之前执行}
public class D0905异常 {
public static void main(String[] args) {
int a = 10, b = 1;
TestException(a, b);
}
static boolean TestException(int a, int b){
try{
System.out.println(a/b);
}catch(ArithmeticException e){// 声明,此处可能抛出"算术异常"
System.out.println("系统维护中,请稍后重试");
return false;
}finally{
System.out.println("---END---");
}
return true;
}
}

自定义异常throw
自定义异常类,继承Excption类
一般需要写一个带参构造方法

public class D0906自定义异常 {

public static void main(String[] args) {
int a = 10;
TestException(a);
}
static boolean TestException(int money){
try{
if (money < 10000){
// 拋一個異常對象
throw new DidiException("系統升級,請半年后重試");
}
}catch(Exception e){// 声明,此处可能抛出"算术异常"

e.printStackTrace();

return false;
}finally{
System.out.println("---END---");
}
return true;
}
}

class DidiException extends Exception{
public DidiException(String message){
super(message);
}
}


IO

File类

File f = new File("AhLog.txt");// 相对路径,相对于整个程序的根目录
File f2 = new File("D:/AhLog.txt");// 绝对路径
File f3 = new File("D:");// 文件夾

boolean _文件是否存在 = f.exists();
boolean _是文件夹吗 = f.isDirectory();
boolean _是文件吗 = f.isFile();
String _文件名 = f.getName();
String _文件全名 = f.getAbsolutePath();
long _修改时间 = f.lastModified();

文件扫描(递归)


static void 递归查找文件(String path){
File f = new File(path);
System.out.println("------开始查找["+path+"]----------");
// 获取文件夹下所有的文件(包括文件夹)
File[] fs = f.listFiles();
for (File file : fs) {
//
if (file.isDirectory()){
递归查找文件(file.getAbsolutePath());
}else{
System.out.println(file.getAbsolutePath());
}
}
}
调用:
public static void main(String[] args) {
递归查找文件("D:");
}
字节流

FileInputStream/FileOutputStream

优点:处理文件效率高.
缺点:一个字节一个字节地处理,对应中文可能出现乱码.

例:文件复制(从文件a读入字节流,直接输出到文件b)

static void CopyFile(String a, String b) {
try {
FileInputStream fis = new FileInputStream(a);
FileOutputStream fos = new FileOutputStream(b);
byte[] buffer = new byte[2048];
while (true) {
int read = fis.read(buffer);
if (read == -1){
break;
}
fos.write(buffer);
}

fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("----------END--------------");
}


字符流
专门应对字符
static void 读文件() {
try {
FileReader fr = new FileReader("D:\\abc.txt");
BufferedReader br = new BufferedReader(fr);

String s;
while (true) {
s = br.readLine();
if (s == null) {// 没读到数据(文件完了)
break;
}
System.out.println(s);
}

br.close();
fr.close();

} catch (IOException e) {
e.printStackTrace();
}
}

static void 写文件() {
try {
FileWriter fw = new FileWriter("D:\\abc2.txt");
BufferedWriter bf = new BufferedWriter(fw);
bf.write("どうぞ よろしく お愿いします");

bf.close();
fw.close();

} catch (IOException e) {
e.printStackTrace();
}
}
序列化
使一个类可被序列化,需要两步:
1.implements Serializable
2.生成序列号:
消除警告,权宜之计 private static final long serialVersionUID = 1L;
有代码版本识别功能
 修改类的代码,删除序列号
 再生成就是新的序列号 private static final long serialVersionUID = 5772255382967012814L;

transient 修饰的变量,不会被序列化

序列化 示例:将(new)对象序列化到文件中
反序列化 示例:再从文件中读出对象
package ah.day11;

import java.io.*;

public class D1101序列化 {

public static void main(String[] args) throws Exception {
序列化();
反序列化();
}

// 把对象写到文件中
static void 序列化() throws IOException {
Dog g = new Dog();
g.setName("tolangpu");

File f = new File("D:\\obj.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(g);

oos.close();
fos.close();
}

// 从文件读出对象
static void 反序列化() throws Exception {
File f = new File("D:\\obj.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Dog obj = (Dog) ois.readObject();
System.out.println(obj);

ois.close();
fis.close();
}

}

class Dog implements Serializable {
// 序列号
// private static final long serialVersionUID = -5623386584421135084L;

private static final long serialVersionUID = 5772255382967012814L;

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

void m() {
System.out.println("汪");
}

}



多线程

第一个线程
public static void main(String[] args) {
Thread currentThread = Thread.currentThread();
System.out.println(currentThread);
}

Java线程编码方式
继承Thread类
重写run方法
实例化该对象,并调用start()方法.
示例代码说明:为了延长线程执行时间,在for循环内加Thread.sleep(毫秒)方法
public class D1104多线程 {

public static void main(String[] args) throws InterruptedException {

MyThread t = new MyThread();
// t.run();
t.start();

for (int i = 0; i < 100; i++) {
Thread.sleep(50);
System.out.println("寫作業");
}
}
}

class MyThread extends Thread {

@Override
public void run() {
System.out.println(Thread.currentThread());
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" 聽歌");
}
}

}

实现runnable接口
还是要用到Thread类,
还是要使用start()启动线程,
还是要重写run方法.
只不多需要多实例化一个对象.
package ah.day11;

public class D1105多线程R {

public static void main(String[] args) {
MyThreadR r = new MyThreadR();
Thread t = new Thread(r);
t.start();

for (int i = 0; i < 100; i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("写作业");
}
}
}

class MyThreadR implements Runnable {

@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" 听音乐");
}
}
}


线程的优先级
t.setPriority(Thread.MAX_PRIORITY); // 10
t.setPriority(Thread.NORM_PRIORITY); // 默认都是普通优先级 5
t.setPriority(Thread.MIN_PRIORITY); // 1

线程状态
新建(new)
就绪(start())
运行(run()ing)
死亡(run(执行完毕))
阻塞 等待/阻塞/睡眠

Sleep() And interrupt()方法
Thread.sleep(1000);//睡1s,记得加try catch
尽量不要使用interrupt()打断睡觉的线程
Yield()方法:
礼不下庶人
暂停当前正在执行的线程对象,让其他线程执行(只让位给优先级相同或更高的线程)
package ah.day11;

public class D1108Yield {

public static void main(String[] args) {
Thread t1 = new MyThread08();
t1.setName("1");
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();

Thread t2 = new MyThread08();
t2.setName(" 2");
t2.start();
}
}

class MyThread08 extends Thread {
@Override
public void run() {
String name = currentThread().getName();
int p = currentThread().getPriority();

for (int i = 0; i < 100; i++) {
if (i % 10 == 0) {

System.out.println(name + ":" + p + " i= " + i + " yield");
yield();
} else {
System.out.println(name + ":" + p + " i= " + i);
}
}
}
}

Join()方法:
通俗:等我做完
等待该线程执行完毕
package ah.day11;

public class D1109 {

public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread09();
t.start();

for (int i = 0; i < 10; i++) {
if (i == 5) {
// 等待线程t做完
t.join();
}

Thread.sleep(100);

System.out.println(Thread.currentThread().getName() + " : " + i);
}
}

}

class MyThread09 extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(" " + currentThread().getName() + " : " + i);
}
}
}


线程同步
package ah.day11;

public class D1110取钱 {

public static void main(String[] args) {
Runnable r = new 取钱();
Thread _User = new Thread(r,"持卡人");
_User.start();
Thread _thief = new Thread(r,"贼");
_thief.start();

}


}
// 线程同步
class 取钱 implements Runnable{
private int money=1000;
public void whithDraw(){
String name = Thread.currentThread().getName();
synchronized (this) {//同步代码块
if (money >= 1000) {
System.out.println(name + "取钱中...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
money -= 999;
System.out.println(name + "取钱完毕,您的余额是:¥" + money);
}else{
System.out.println(name+" 余额不足");
}
}
}
@Override
public void run() {
whithDraw();
}

}

另一种线程同步方式(对方法加线程同步,该方法同一时间,只能被一个线程调用)
public synchronized void whithDraw(){}
卖票
1.实现runnable接口
package ah.day12;

//1.实例化一个Runnable对象
//2.main方法中,仅实例化一个Runnable对象
//3.main方法中,开3个线程
public class D1201卖票 {

public static void main(String[] args) {
Runnable r = new 卖票();

Thread t1 = new Thread(r, "窗口1");
Thread t2 = new Thread(r, "窗口2");
Thread t3 = new Thread(r, "窗口2");

t1.start();
t2.start();
t3.start();
}
}

class 卖票 implements Runnable {
private int tickts = 100;

private void sell() {
while (true) {
synchronized (this) {// 锁住:Runnable r = new 卖票();
if (tickts > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("卖出第" + tickts + "张票");
tickts--;// tickts = tickts -1 // tickts-=1;
} else {
break;
}
}
}
}

@Override
public void run() {
// 卖票
sell();
}

}
2.继承Thread类
package ah.day12;

//如果卖票的对象new了3次
//1.票数必须是static的(保证在系统中的唯一性)
//2.无中生有,造一个Object对象(保证其唯一性),锁的时候就锁这个对象
public class D1201卖票extendsThread {

public static void main(String[] args) {

Thread t1 = new 卖票2();
Thread t2 = new 卖票2();
Thread t3 = new 卖票2();

t1.start();
t2.start();
t3.start();

}
}

class 卖票2 extends Thread {
private static int tickts = 100;
private static Object obj = new Object();

private void sell() {
while (true) {
synchronized (obj) {
if (tickts > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("卖出第" + tickts + "张票");
tickts--;// tickts = tickts -1 // tickts-=1;
} else {
break;
}
}
}
}

@Override
public void run() {
// 卖票
sell();
}
}







后台线程(守护线程)
守护线程一定要在start前开启
前台线程接受,守护线程就结束
package ah.day13;

public class D1301守护线程 {

public static void main(String[] args) throws InterruptedException {
MyThread1301 t = new MyThread1301();
t.setDaemon(true);
t.start();


for (int i = 0; i < 30; i++) {
Thread.sleep(100);
System.out.println(i);
}
}
}

class MyThread1301 extends Thread {
@Override
public void run() {
for (int i = 0;; i++) {
if (i % 100 == 0) {
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----------守护----" + i);
}
}
}
}


网络编程

控制台运行Socket
1. 前提:.class文件已经生成(现再MyEclipse中跑一次,注意关闭程序)
2. 进入bin文件夹,左手按Shift,在空白处右键选择”在此处打开命令窗口”
3. 输入java 包名.类名
4. 回车
查看端口使用情况
查看端口使用情况:
netstat -ano
-a 显示所有连接和监听端口。
-n 以数字形式显示地址和端口号。 此选项可以与 -a选项组合使用
-o 显示与每个连接相关的所属进程 ID。

精确查看端口
netstat -ano|findstr "8848"

查看进程
tasklist|findstr "11044"



字符流(发消息)
package ah.day14;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class D1403SocketMultiThread {
public static final int PORT = 8850;

public static void main(String[] args) {
Thread t = new IpMsgServce();
t.start();

(new IpMsgClient()).start();

}
}

/**
* 服务器
*
* @author Administrator
*
*/
class IpMsgServce extends Thread {
private void myServer() throws IOException {
// 服务器Socket
ServerSocket ss = new ServerSocket(D1403SocketMultiThread.PORT);

// 通讯用的socket
Socket s = null;

while ((s = ss.accept()) != null) {
// 读入请求
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

String str = br.readLine();
InetAddress ip = s.getInetAddress();
String hostAddress = ip.getHostAddress();
System.out.println(hostAddress + "说:" + str);

br.close();
isr.close();
is.close();
// 通讯用的socket对象,必须关闭
s.close();
}

ss.close();

}

@Override
public void run() {
try {
myServer();
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 客户端
*
* @author Administrator
*
*/
class IpMsgClient extends Thread {
private void myClient() throws IOException {

Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入对方IP:");
String toIp = sc.nextLine();
Socket s = new Socket(toIp, D1403SocketMultiThread.PORT);

// 发送消息
OutputStream os = s.getOutputStream();
PrintWriter pr = new PrintWriter(os);

System.out.println("请输入要说的话:");
String str = sc.nextLine();

pr.println(str);
pr.flush();

pr.close();
os.close();

s.close();
}

}

@Override
public void run() {
try {
myClient();
} catch (IOException e) {
e.printStackTrace();
}
}
}



字节流(发文件)
客户端:读入文件, 输出Stream
package ah.day14;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class D1404FileS {

public static void main(String[] args) throws IOException {
byte[] bs = new byte[2048];
ServerSocket ss = new ServerSocket(8848);
Socket s = ss.accept();

// 取文件名(字符流,方便取文件名)
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String fileName = br.readLine();

// 以下操作为字节流(效率高)
FileOutputStream fos = new FileOutputStream("C:\\" + fileName);
while (true) {
// 收消息(InputStream)
int ret = is.read(bs);
if (ret == -1) {
System.out.println("接收完毕");
s.close();
return;
}

// 写文件(OutputStream)
fos.write(bs, 0, ret);
}
}

}



服务器:读入Stream, 输出文件
package ah.day14;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

public class D1404FileC {

public static void main(String[] args) throws IOException {
byte[] bs = new byte[2048];
Socket s = new Socket("127.0.0.1", 8848);

// 先发送文件名(字符流,方便取文件名)
File f = new File("D:\\baidu.png");
OutputStream os = s.getOutputStream();
PrintWriter pr = new PrintWriter(os);
pr.println(f.getName());
pr.flush();

// 读入文件(InputStream)
FileInputStream fis = new FileInputStream(f);
while (true) {
int ret = fis.read(bs);
if (ret == -1) {
System.out.println("发送完毕");
s.close();
return;
}

// 发送信息(OutputStream)
os.write(bs, 0, ret);
}

}

}


Junit
单元测试

JDBC
导入外部jar包
项目->右键->Build Path(构建路径)->Add External Archives...(010瓶)



Jar包导入后认的是绝对路径,如果jar包位置改变,需要修改:
项目->右键->Build Path(构建路径)->Configure Build Path...

->重新编辑(Edit)jar包的路径



基本SQL语句
查 SELECT * FROM testuser

查询全部 ResultSet rs = ps.executeQuery();
返回的是结果集
SELECT * FROM testuser
WHERE uname ='Dog' AND pwd='123'

登录(根据用户名和密码查询用户数据)
增: 插入新数据(id自增长,不管) INSERT INTO testuser
(uname, pwd)
VALUES
('Andy', '1') int ret = ps.executeUpdate();
返回的是受影响行数
删: 根据用户名删除数据 DELETE FROM testuser
WHERE uname='Andy'
改: 根据用户名修改密码 UPDATE testuser SET pwd='9' WHERE uname='Andy'

模拟用户登录
package ah.day15;

import java.sql.*;
import java.util.Scanner;

public class D1501JDBC {

public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

public static void main(String[] args) throws ClassNotFoundException,
SQLException {

// 加载数据库驱动
Class.forName(DRIVER);

// 获取数据库链接
Connection conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);

// 创建语句
Statement sta = conn.createStatement();

String sUname, sPwd;
{
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
sUname = sc.nextLine();

System.out.println("请输入密码:");
sPwd = sc.nextLine();
}

String sql = "SELECT * FROM testuser WHERE uname ='" + sUname + "' AND pwd='" + sPwd + "'";
System.out.println(sql);
ResultSet rs = sta.executeQuery(sql);// 语句.执行询问();

if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}

// 关闭连接
rs.close();
sta.close();
conn.close();
}
}

SQL注入,绕过登录验证:
请输入用户名:
Dog'--
请输入密码:
1
SELECT * FROM testuser WHERE uname ='Dog'-- ' AND pwd='1'
登录成功


使用preparedStatement防止SQL注入
package ah.day15;

import java.sql.*;
import java.util.Scanner;

public class D1502JDBCPrepSat {

public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

public static void main(String[] args) throws ClassNotFoundException,
SQLException {

String sUname, sPwd;
{
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
sUname = sc.nextLine();

System.out.println("请输入密码:");
sPwd = sc.nextLine();
}

// 加载数据库驱动
Class.forName(DRIVER);

// 获取数据库链接
Connection conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);

// 创建语句
PreparedStatement ps = conn.prepareStatement("SELECT * FROM testuser WHERE uname = ? AND pwd=?");// 预编译
ps.setString(1, sUname);
ps.setString(2, sPwd);

ResultSet rs = ps.executeQuery();

if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}

// 关闭连接
rs.close();
ps.close();
conn.close();
}
}

JDBC的事务处理
package ah.day15;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class D1504RollBack {
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

private static Connection conn;

public static void main(String[] args) {
// 获取数据库链接
try {
conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);
// 1.设置手动提交
conn.setAutoCommit(false);

String sql = "INSERT INTO testuser (uname, pwd) VALUES ('Andy', '1')";
PreparedStatement ps = conn.prepareStatement(sql);// 预编译
ps.executeUpdate();

System.out.println(1 / 0);

sql = "INSERT INTO testuser (uname, pwd) VALUES ('Bob', '1')";
ps = conn.prepareStatement(sql);// 预编译
ps.executeUpdate();

} catch (SQLException e) {
System.out.println("出现异常");
// 3.回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}

// 2.提交
try {
conn.commit();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}

}

}


DAO,DataAccessObject,数据访问对象
1. 创建基类(BaseDao.java)
1.1 写常量
1.2 定义成员变量:Connection,PreparedStatment,ResultSet
1.3 定义方法: 获取连接, 关闭连接
2. 创建子类Dao
2.1 继承BaseDao
2.2 super.打开连接()
2.3 创建语句
2.4 执行语句
2.5 关闭连接(finally)
3.在单独的类里创建main方法测试

package ah.day16;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// 所有 D数据A访问O对象 的基类
public class BaseDao {
public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

protected Connection conn = null;
protected PreparedStatement ps = null;
protected ResultSet rs = null;

/**
* 获取连接
*
* @throws SQLException
*/
void getConn() {

try {
// 加载数据库驱动
Class.forName(DRIVER);

// 获取数据库链接
conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);

} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}

/**
* 关闭连接
*/
void closeConn() {
try {

if (rs != null) {
rs.close();
rs = null;
}

if (ps != null) {
ps.close();
ps = null;
}

if (conn != null) {
conn.close();
conn = null;
} else {
// 如果conn ≠ null
// do nothing
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

package ah.day16;

import java.sql.ResultSet;
import java.sql.SQLException;

public class D1602MoviesDao extends BaseDao {
/**
* 查询电影的票价
*
*/
public double getMovies() {

try {
// 1.获取连接
super.getConn();// super. 可省略
// 2.创建语句
ps = conn.prepareStatement("SELECT * FROM movies WHERE mname = ?");
ps.setString(1, "战狼");

rs = ps.executeQuery();
if (rs.next()) {
double price = rs.getDouble("price");
return price;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}

// 没取到的时候
return 0.0;
}

public ResultSet getAllMovies() {

try {
// 1.获取连接
super.getConn();// super. 可省略
// 2.创建语句
ps = conn.prepareStatement("SELECT * FROM movies");

rs = ps.executeQuery();

return rs;
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}

return null;
}

}

测试: 类名略
public static void main(String[] args) throws ClassNotFoundException,
SQLException {
D1602MoviesDao dao = new D1602MoviesDao();
double price = dao.getMovies();
// 在调用方打印查询结果
System.out.println(price);
}


注意事项:
1.尽量不要用SELECT * FROM 表,把*换成具体的数据库表的列名,中间用逗号分隔,比如:
SELECT
id,
price
FROM
movies
2.使用StringBuilder拼接SQL语句,注意前后都加上一个空格
StringBuilder sb = new StringBuilder();
sb.append(" SELECT ");
sb.append(" id, ");
sb.append(" price ");
sb.append(" FROM ");
sb.append(" movies ");
sb.append(" WHERE ");
sb.append(" mname = ? ");
ps = conn.prepareStatement(sb.toString());

使用List取多条数据对象
1.创建POJO(简单JAVA对象)
1.1 主要包括私有成员变量和get/set方法
1.2 成员变量和数据库中的字段保持一致
2.编写Dao中的方法
2.1 从ResultSet中取出结果,
2.2 实例化(new)POJO类的对象
2.3 将”2.1”取到的结果设置到”2.2”的对象中
2.4 将POJO类的对象add到返回的List中

1.创建POJO(简单JAVA对象)
package ah.day16;

/**
* 贿赂类(JavaBean,POJO)
*
* @author Administrator
*
*/
public class Bribe {

public Bribe(int id, String who, String when, String how, String what,
String howmuch) {
super();
this.id = id;
this.who = who;
this.when = when;
this.how = how;
this.what = what;
this.howmuch = howmuch;
}

private int id;
private String who;
private String when;
private String how;
private String what;
private String howmuch;
// get set方法略
}

2.编写Dao中的方法
BaseDao.java略
package ah.day16;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class D1602MoviesDao extends BaseDao {

// public ResultSet getAllMovies() {
public List<Bribe> getAll受贿记录() {

List<Bribe> lst = new ArrayList<Bribe>();
try {
// 1.获取连接
super.getConn();// super. 可省略
// 2.创建语句
ps = conn.prepareStatement("SELECT * FROM bribe");

rs = ps.executeQuery();
while (rs.next()) {
int _id = rs.getInt("id");
String _who = rs.getString("who");
String _when = rs.getString("when");
String _how = rs.getString("how");
String _what = rs.getString("what");
String _howmuch = rs.getString("howmuch");
Bribe b = new Bribe(_id, _who, _when, _how, _what, _howmuch);

lst.add(b);
}
return lst;
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}

return null;
}

}


package ah.day16;

import java.sql.*;
import java.util.List;

/**
* 调用方:处理业务逻辑
*
* @author Administrator
*
*/
public class D1601Test {

public static void main(String[] args) throws ClassNotFoundException,
SQLException {

// 1.实例化DAO对象
D1602MoviesDao dao = new D1602MoviesDao();

// 2.把数据取出来
List<Bribe> all受贿记录 = dao.getAll受贿记录();

// 3.处理数据
for (Bribe b : all受贿记录) {
System.out.println(b.getWho() + ":" + b.getHowmuch());
}
}
}

Batch
不同点:
preparedStatment只能执行一种SQL语句,参数可以不同
Statement可以执行任意的一批不同的SQL语句
相同点:
.addBatch()
执行都使用:int[] executeBatch = ps.executeBatch();



存储过程
MySQL存储过程
DROP PROCEDURE
IF EXISTS findpwd;

CREATE PROCEDURE findpwd (
IN iname VARCHAR (20),
OUT opwd VARCHAR (20)
)
BEGIN
SELECT
pwd INTO opwd
FROM
customer
WHERE
uname = iname;


END

MySQL调用存储过程
SET @iname='Andy';
CALL findpwd(@iname,@opwd);
SELECT @opwd

JAVA调用存储过程
输出型的参数需要注册,执行之后可以取值
package ah.day16;

import java.sql.CallableStatement;
import java.sql.SQLException;

public class D1604Prod extends BaseDao {
public static void main(String[] args) {
new D1604Prod().testProd();
}

public void testProd() {

try {
getConn();
CallableStatement cs = conn.prepareCall("call findpwd(?,?)");
cs.setString(1, "我爱你");// 输入型参数
// java.sql.Types.INTEGER
cs.registerOutParameter(2, java.sql.Types.VARCHAR);// 输出型参数(1.注册)

cs.executeQuery();
String pwd = cs.getString(2);// 输出型参数(2.取值)
System.out.println(pwd);
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}
}
}




练习:
创建
DROP PROCEDURE
IF EXISTS proc1;
CREATE PROCEDURE `proc1`(in var1 int, out var2 int)
BEGIN
set var2= var1+1;
END
调用(--注释在Workbench中无效,只能用#注释)
set @var1 = 10; #输入参数
set @var2 =10; #输出参数
CALL proc1(@var1, @var2);
select @var2 #查看输出参数

反射
获取私有的构造方法
package ah.day17;

public class Dog {

// ---private-----------------
private Dog() {
System.out.println("Dog 对象被创建");
}

private void m(String s) {
System.out.println("旺旺:" + s);
}

// ---public-----------------
public Dog(String name) {
System.out.println("Dog:" + name + " 对象被创建");
}

public void m() {
System.out.println("旺旺!");
}
}

package ah.day17;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class D1701反射调用方法 {

public static void main(String[] args) throws Exception {
// new Dog();

// Class<?> forName1 = String.class;
// System.out.println(forName1);
//
// Class<?> forName2 =Class.forName("java.lang.String");
// System.out.println(forName2);
// 1.获取类
Class<?> forName = Class.forName("ah.day17.Dog");

// 2.获取构造方法
// Constructor<?>[] declaredConstructors =
// forName.getDeclaredConstructors();// 获取私有的构造方法
Constructor<?> cs = forName.getDeclaredConstructor();
cs.setAccessible(true);

// 2.1 实例化对象(new)
Object obj = cs.newInstance();
Dog d = (Dog) obj;
System.out.println(d);

// 3.获取私有方法
Method m = forName.getDeclaredMethod("m", String.class);
m.setAccessible(true);
m.invoke(obj, "牛奶");
}
}

读取配置文件创建对象/调用方法
配置文件config.properties
className=ah.day17.Dog
methodName=m

Java代码
package ah.day17;

import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

public class D1702配置文件创建对象 {

public static void main(String[] args) throws IOException {

Properties p = new Properties();
// 1.读入配置文件
FileReader _fileReader = new FileReader("src/config.properties");
p.load(_fileReader);
_fileReader.close();

// 2.操作配置信息
String className = p.getProperty("className", "默认值,取不到数据时的值");

String methodName = p.getProperty("methodName", "");
System.out.println(className + ":" + methodName);

// 3.创建对象,并调用方法
createClassAndExeMethod(className, methodName);
}

public static void createClassAndExeMethod(String className,
String methodName) {
try {
Class<?> cls = Class.forName(className);
Constructor<?> cs = cls.getConstructor(String.class);
Object obj = cs.newInstance("哈士奇");

Method m = cls.getMethod("m");
m.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}

}



设计模式
类的关系
继承
UML类图设计中,继承用一条带空心三角箭头的实线表示,从子类指向父类,或者子接口指向父接口

实现
在UML类图设计中,实现用一条带空心三角箭头的虚线表示,从类指向实现的接口

依赖
简单的理解,依赖就是一个类A使用到了另一个类B
这种使用关系是偶然的、临时性的、非常弱的
类B的变化会影响到类A
代码层面,表现为类B作为参数被类A在某个method方法中使用
UML类图设计中,依赖关系用由类A指向类B的带箭头虚线表示

class A
{
public void Method(依赖B b)
{
}
}
class 依赖B
{
}
关联
关联是语义级别的一种强依赖关系
关联可以是单向、双向的
表现在代码层面,为被关联类B以类的属性形式出现在关联类A中
UML类图设计中,关联关系用由关联类A指向被关联类B的带箭头实线表示,在关联的两端可以标注关联双方的角色和多重性标记

class A
{
private 关联B myVar;
public 关联B MyProperty
{
get { return myVar; }
set { myVar = value; }
}
}
class 关联B
{
}
组合(合成) ·聚合
组合也是关联关系的一种特例
体现的是一种contains-a的关系
也称为强聚合
表现在代码层面,和关联关系是一致的,只能从语义级别来区分
UML类图设计中,组合关系以实心菱形加实线箭头表示

组合示例:人由大脑.心脏等组成

聚合是关联关系的一种特例
是整体与部分的关系,即has-a的关系
表现在代码层面,和关联关系是一致的,只能从语义级别来区分
UML类图设计中,聚合关系以空心菱形加实线箭头表示

聚合示例:孩子和家庭/人和人群


设计六原则
开闭原则(核心)
(Open Close Principle)
理论:对扩展开放,对修改关闭(Open for extension)
实践:尽量使用接口和抽象类(Cloded for modification)

里氏代换原则
(Liskov Substitution Principle, LSP)
理论:父类可以出现的地方,子类一定可以出现
父类替换成子类,程序的行为没有变化,所以父类可以代表任何子类---体现其可重用性
实践:以父类名义声明子类对象

依赖倒转原则(基础)
(Dependence Inversion Principle)
理论:抽象不应该依赖细节,细节应该依赖抽象---即对接口编程,而不是对实现编程.

接口隔离原则
(Interface Segregation Principle)
理论:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

迪米特法则(最少知道原则)(Demeter Principle)
理论:各模块尽量独立


合成复用原则(Composite Reuse Principle)
理论:尽量使用合成/聚合的方式,而不是使用继承(继承毕竟有耦合,父类改了子类就要改)。
实践:Business层调用Dao层,有一个Dao对象的变量,而不是继承Dao

单例模式
1. 懒汉式(第一次用的时候加载.怕被抢,需要线程同步,因此影响效率)
2. 饿汉式(猴急,占了不用)
(比如调了该类的其他static方法,其单例对象也会加载;而其他方式此类情况单例对象不加载)
3. 综合式(使用静态内部类,调用该类属于懒汉(不占用),该类里面属于饿汉,调用即加载)
效果上类似懒汉,但是无需线程同步
/**
* 1.私有的 实例对象 2.私有的 构造方法 3.公开化 获取实例(getInstance)
*/
public class Single {
public static void main(String[] args) {
Lazy.getInstance();
System.out.println("-----------");
Hungry.getInstance();
System.out.println("-----------");
Singleton.getInstance();
}
}

class Lazy {
private static Lazy instance;

private Lazy() {
System.out.println("懒汉");
}

public static synchronized Lazy getInstance() {
System.out.println("Lazy getInstance");
// 用时加载,影响性能(要做线程同步)
if (instance == null) {
instance = new Lazy();
}
return instance;
}

}

class Hungry {
// 立马加载,闲置资源(很多类都这么干的时候)
private static Hungry instance = new Hungry();

private Hungry() {
System.out.println("饿汉");
}

public static Hungry getInstance() {
System.out.println("Hungry getInstance");
return instance;
}
}

class Singleton {
// 化实例对象为静态内部类
// 用时建类,建类加载
// 不浪费,无同步
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}

private Singleton() {
System.out.println("静态内部类");
}

public static Singleton getInstance() {
System.out.println("Singleton getInstance");
return Holder.INSTANCE;
}
}

简单工厂模式
package designpattern.bean;
public abstract class Car {
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}

public abstract void drive();
}
package designpattern.bean;
public class Benz extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}
package designpattern.bean;
public class Bmw extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}

根据字符串,创建类
package designpattern;
import designpattern.bean.*;
public class C简单工厂 {
public static void main(String[] args) {
Car car = FactoryS.createCar("benz");
car.setName("benz");
car.drive();
}
}

class FactoryS {
public static Car createCar(String car) {
Car c = null;
if ("Benz".equalsIgnoreCase(car))
c = new Benz();
else if ("Bmw".equalsIgnoreCase(car))
c = new Bmw();
return c;
}
}



工厂模式
工厂和简单工厂相比,工厂有了扩展,有了统一的规范
工厂模式:定义一个创建对象的接口,但由子类决定实例化哪一个,工厂方法的实例化推迟到了子类。

package designpattern;

import designpattern.bean.*;

public class C工厂 {
public static void main(String[] args) throws Exception {
FactoryAbs d = new BenzFactory();
Car c = d.createCar();
c.setName("benz");
c.drive();
}
}

// 抽象工厂
abstract class FactoryAbs {
public abstract Car createCar() throws Exception;
}

class BenzFactory extends FactoryAbs {
public Car createCar() throws Exception {
return new Benz();
}
}

class BmwFactory extends FactoryAbs {
public Car createCar() throws Exception {
return new Bmw();
}
}




抽象工厂模式
---提供一个接口,用于创建相关和依赖对象的家族,而不需要指定具体类。

工厂模式的优点:
1.工厂方法封装了对象创建的细节,将对象创建代码和其他部分脱离,减少相干性.
2.有利于同类对象创建的统一管理和控制
3.你所关心的仅仅是工厂方法返回的接口方法,不必关心实现细节

抽象工程和工厂相比,制造业升级!能制造产品2了

package designpattern;

import designpattern.bean.*;

public class C抽象工厂 {
public static void main(String[] args) throws Exception {
// 找奔驰工厂
AbstFactory f = new BenzFactory2();
// 造车造体育馆随意
Arena arena = f.createArena();
arena.setName("Mercedes Benz");
arena.logo();
}
}

// 抽象产品(竞技场)
abstract class Arena {
private String name;

public abstract void logo();

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

// 具体产品(Bmw和Audi同理)
class BenzArena extends Arena {

@Override
public void logo() {
System.out.println(this.getName());
}
}

class BmwArena extends Arena {
@Override
public void logo() {
System.out.println(this.getName());
}
}

// 抽象工厂
abstract class AbstFactory {// brand:品牌
public abstract Car createCar() throws Exception;

public abstract Arena createArena() throws Exception;
}

// 具体工厂
class BenzFactory2 extends AbstFactory {

@Override
public Car createCar() throws Exception {
return new Benz();
}

@Override
public Arena createArena() throws Exception {
return new BenzArena();
}

}

class BmwFactory2 extends AbstFactory {

@Override
public Car createCar() throws Exception {
return new Benz();
}

@Override
public Arena createArena() throws Exception {
return new BenzArena();
}
}

适配器模式
痛点: 一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的
实例: 美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V

package adapter;

public class C适配器 {
public static void main(String[] args) {
WinAdapter audioPlayer = new WinAdapter();

audioPlayer.play("win10", "截图");
audioPlayer.play("xp", "绘图");
}
}

class Win_XP {
public void prtSc(String fileName) {
System.out.println("Name: " + fileName);
}
}

class Win_10 {
public void pic(String type, String fileName) {
System.out.println("Type: " + type + " Name: " + fileName);
}
}

interface BaseAdaoter {
public void play(String type, String fileName);
}

class WinAdapter implements BaseAdaoter {
Object os;

@Override
public void play(String type, String fileName) {
if ("win10".equals(type)) {
os = new Win_10();
((Win_10) os).pic(type, fileName);
} else {
os = new Win_XP();
((Win_XP) os).prtSc(fileName);
}
}

}


观察者模式
手工实现观察者模式
皇上有很多下人(List)
皇上要找下人
皇上发话,所有下人都要听谕
import java.util.ArrayList;
import java.util.List;

public class C观察者模式 {
public static void main(String[] args) {

皇上 h = new 皇上();
h.招下人(new 奴才());
h.招下人(new 奴才());
h.口谕();

}
}

class 皇上 {
List<下人> lst = new ArrayList<下人>();

public void 招下人(下人 x) {
lst.add(x);
}

public void 口谕() {
for (下人 x : lst) {
x.听谕();
}
}
}

interface 下人 {
void 听谕();
}

class 奴才 implements 下人 {
@Override
public void 听谕() {
System.out.println("奴才遵旨");
}
}
JAVA自带观察者实现
1. 继承Observable
2. 实现Observer
3. Observable添加Observer
4. Observable标榜setChanged(),并且notifyObservers(),缺一不可
import java.util.Observable;
import java.util.Observer;

public class C观察者模式继承版 {
public static void main(String[] args) {

皇上 h = new 皇上();
h.addObserver(new 奴才());
h.addObserver(new 奴才());
h.口谕();
}
}

class 皇上 extends Observable {

void 口谕() {
// 标记此 为已改变的对象
setChanged();
// 通知所有观察者
notifyObservers();
}
}

class 奴才 implements Observer {

@Override
public void update(Observable o, Object arg) {
System.out.println("皇上口谕");
}
}




package designpattern.bean;
public abstract class Car {
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}

public abstract void drive();
}
package designpattern.bean;
public class Benz extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}
package designpattern.bean;
public class Bmw extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}

根据字符串,创建类
package designpattern;
import designpattern.bean.*;
public class C简单工厂 {
public static void main(String[] args) {
Car car = FactoryS.createCar("benz");
car.setName("benz");
car.drive();
}
}

class FactoryS {
public static Car createCar(String car) {
Car c = null;
if ("Benz".equalsIgnoreCase(car))
c = new Benz();
else if ("Bmw".equalsIgnoreCase(car))
c = new Bmw();
return c;
}
}












内部类
成员内部类
Outter.Inner inner = new Outter().new Inner();

静态内部类
访问外部类的静态成员
Outter.Inner inner = new Outter.Inner();

局部内部类
方法内部new
方法内部的变量,只能访问final的


匿名内部类
import java.util.Arrays;
import java.util.Comparator;

public class D0903数组降序 {
// 数组降序排列注意
// 1.定义降序的类, implements Comparator<Integer>
// 2.必须使用包装类,不能使用int等基本数据类型的数组
public static void main(String[] args) {
Integer red[] = { 3, 1, 6, 7, 9, 15 };
Arrays.sort(red, new ArraySortDesc());
for (int i : red) {
System.out.println(i);
}
}
}

class ArraySortDesc implements Comparator<Integer> {

@Override
public int compare(Integer o1, Integer o2) {
return (o1 < o2) ? 1 : -1;
}

}







《Java》
环境变量

新建 JAVA_HOME C:\Program Files (x86)\Java\jdk1.8.0_31
一般存在,添加 Path ;%JAVA_HOME%\bin
不存在就新建 classpath .;%JAVA_HOME%\lib;

命令行运行Java代码
D:\Test.java
public class Test {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
C:\Users\bonld_000>cd..

C:\Users>cd..

C:\>D:

D:\>javac Test.java

D:\>java Test
Hello Java

D:\>
MyEclipse字体修改

Windows -> Perferences -> 左上角搜索”font”
Java代码字体:


控制台字体:



输入输出
快速代码:
// 打“main”按Alt+?组合件,点击Enter
public static void main(String[] args)
// 打“syso”按Alt+?组合件,点击Enter
System.out.println("请输入用户名:");
// 自动生辰返回值:ctrl+1 -> 选择“.... new local variable”(新本地变量)
String _s = _sc.nextLine();



import java.util.Scanner;

public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String nextLine = sc.nextLine();
System.out.println("您输入的是:" + nextLine);
System.out.printf("您输入的是:%s", nextLine); // C语言风格输出
sc.close();
}
}

Java注释
第一种注释://单行
第二种注释:/* 多行注释 */
第三种注释:/**+回车键
/**
* Javadoc类型的注释
* @param args
*/
Eclipse中注释的快捷键:Ctrl+?
变量
标识符由A-Z,a-z,0-9,_,$(中文)
0-9不能打头
命名要求:见名知意
变量命名规范:
 Java的命名一般遵循“驼峰标识”:每个单词首字母大写,另外——
 类:首字符大写
 变量:首字母小写
 函数(方法):首字母小写

int $n=1;
Java 8 VS2012(C#.Net Framework 4.5) Dev C++(5.11@2015)
OK Err OK


结构化编程
选择结构
三目运算符
static int getMax(int x, int y){
// if (x >= y){
// return x;
// }else{
// return y;
// }
return (x >= y)?x:y;
}


switch (day) {
case 1:
System.out.println("月曜日");
break;
case 2:
System.out.println("火曜日");
break;
default:
System.out.println("何曜日?");
break;
}
支持字符串
break可以省略,省略的后果是代码继续走下一个case,直到遇到break,一定要注意,不能漏了break
循环结构
 While循环:先判断
 死循环:while(true){...}
 Do...while循环:后判断,最后要加分号”;”
 For循环:简化变量管理
 死循环:for(;;){...}

 退出循环
 break; 退出当前循环
 Continue; 结束本次循环,继续下次循环
 Return; 退出函数,不推荐

运算符
位运算符
重点掌握:
>> 右移(除以2n)
<< 左移(乘以2n)
一般了解:
& 位与(相当于AND)
| 位或(相当于OR)
^ 亦或(叛逆,同0异1)
数组
数组的定义
C语言风格
int a[] = { 1, 2, 3, 4, 5, 6 };

Java风格(面向对象风格)
int[] b = { 5, 6, 7, 8 };

可以不赋初始值(但要指定长度)
int[] c = new int[5];

遍历数组
int[] c = new int[5];

// 写入
for (int i = 0; i < c.length; i++) {
c[i] = i*2;
}

// 输出
for (int i = 0; i < c.length; i++) {
System.out.println(c[i]);
}
// foreach循环遍历数组:只读
for(int n : c){
System.out.println(n);
}

冒泡排序


一个数和其它数比较(循环)
每个数都要做这种比较(再一层循环)
冒泡排序三步走:
循环
交换
回一手(减少比较次数,提高效率)
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
int temp;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] < arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int n : arr) {
System.out.println(n);
}
}


二维数组
int arrC[][] = new int[2][3];
int[][] arrJ = new int[2][3];
int[][] arrJ2 = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };

例:表格数据输出
霸王别姬 阿甘正传 大话西游
Andy 9.5 9.4 9.1
Bob 3 8.7 9
Cat 3 7 1
Dog 9.9 3 3
public static void main(String[] args) {

double[][] films = {
{ 9.5, 9.4, 9.1 },
{ 3, 8.7, 9 },
{ 3, 7, 1 },
{ 9.9, 3, 3 }
};

// 二维数组的遍历
for (int i = 0; i < films.length; i++) {
for (double n : films[i]) {
System.out.print(n + " ");
}
System.out.println();
}
}


题:判断一个3*3的矩阵是不是单位矩阵“Unit Matrix”(对角线上元素是1,其余元素是0)
1 0 0
0 1 0
0 0 1

int[][] m = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};

for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
if ((i == j && m[i][j] == 1)) {
// 1.对角线上元素是1
} else if (i != j && m[i][j] == 0) {
// 2.非对角线上元素是0
} else {
// 3.以上都不满足
System.out.println("不是單位矩陣");
return;
}
}
}

System.out.println("是单位矩阵");

题:矩阵乘法:
设A为m*p的矩阵
B为p*n的矩阵
那么称m*n的矩阵C为矩阵A与B的乘积
记作C=AB
矩阵C中的第i行第j列元素可以表示为:




字符串
长度 s.length()
大小写转换 s.toUpperCase() s.toLowerCase()

去空格 s.trim()
右对齐 String.format("%10s", s)
左对齐 String.format("%-10s", s);
时间转字符串 Date d = new Date();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String sDate = f.format(d);

包含查询 s.contains("晁盖")
子字符串 s.substring(1)
String substring2 = s.substring(3, 3 + 3)
下标查询 s.indexOf("阳跻") :查不到返回-1
s.lastIndexOf("阳跻")

叛空 if (s2 == null || s2.isEmpty())
字符串比较 if ("字符串写左边".equals(变量写右边))

StringBuilder StringBuilder sb = new StringBuilder();
sb.append("诸");
sb.append("葛");
sb.append("孔");
sb.append("明");
System.out.println(sb.toString());
StringBuffer 安全,但效率较低

例:String sFile = "D:\\迅雷下载\\新建文件\\[陈奕迅]喜欢一个人_bd.mp4";
1.求文件名
2.求后缀名
int _最后斜杠的下标 = sFile.lastIndexOf("\\");
int _后缀名的位置 = sFile.lastIndexOf(".");
String _文件名= sFile.substring(_最后斜杠的下标 + 1, _后缀名的位置);
String _后缀名 = sFile.substring(_后缀名的位置);
System.out.println(_文件名);
System.out.println(_后缀名);

类和对象
类是对对象的描述,是创建对象的“模板”,是对象的抽象。
对象是类的一个实例,是类的实例化结果。

类 对象
Scanner sc =new Scanner(System.in)
String s1 = "";
s2 = new String();
s3 = new String();

装箱·拆箱

int a1 = 1000;
装箱 Integer objA =a1;
拆箱 int a2 = objA;

封装
访问修饰符
private(类自己可以用)→default(不加修饰符,包内可用)→protected→public(谁都可以用)

*public:谁都可以使用
*protected:子类可以使用
*private:只有自己可以式样

属性
1.成员变量设为private
2.提供public的get/set方法作为访问器
自动生成属性快捷键

// 私有成员变量
private String who;

// 公共访问器:getter
public String getWho() {
return who;
}

// 公共访问器:setter
public void setWho(String who) {
this.who = who;
}

方法
局部变量·成员变量
成员变量:类里面定义的变量
局部变量:方法中定义的变量;复合语句中定义的变量for(int n : arr){...}
递归
1.阶乘
static int factorial(int n) {
if (n == 0) {
// 0! = 1
return 1;
} else {
// n ≠ 0,n! = n*(n-1)!
return n * factorial(n - 1);
}
}

2.兔子数列
static int rabbit(int m){
// 1月:1
// 2月:1
// 3月:1月+2月
// ...
// m月:(m-1)月+(m-2)月
if (m==1 || m==2){
return 1;
}else{
return rabbit(m-1)+rabbit(m-2);
}
}

构造方法
特点:1.没有返回值;2.方法名必须和类名一致。
无参构造方法:
1.如果不手写一个,系统默认提供一个。new 类():实际上是调用类的构造方法。
2.如果手写带参构造方法,系统不再提供无参构造方法。可以再手写一个无参构造方法。
构造方法的主要作用:初始化对象——为成员变量赋初始值

MyEclipse中构造方法自动生成:


重载
1.方法名相同
2.参数列表不同:
a) 参数类型相同,个数不同
b) 参数个数相同,类型不同
3.重载不管返回类型
静态
静态方法
不需要new(实例化对象)就可以使用的方法。
使用方式:类名.静态方法名(参数列表);
如果是在当前类中调用,类名可以省略。
public class D0503静态 {

// 静态方法
public static void main(String[] args) {
D0503静态.method静态方法();// 本类中,通过类名调用
method静态方法();// 本类中,也可以直接调用

Dog.method静态方法();// 其他类中,“必须”通过类名调用

Dog _dog = new Dog();
_dog.method普通方法();// 非静态方法(普通方法),必须实例化对象(new),通过对象调用
}

void method普通方法() {
System.out.println("D0503静态.java method普通方法");
}

static void method静态方法() {
System.out.println("D0503静态.java method静态方法");
}
}

静态变量


静态代码块
普通代码块:类被创建(new)的时候执行,比构造方法还早。
静态代码块:类被使用的时候执行,比普通代码块还早。
继承
关键字:子类 extends 父类
this和super
this 自己的
super 父类的
super():父类构造方法
super.XXX:父类的成员(方法或变量)
再论构造方法
 无论子类构造方法带不带参数,默认都是执行父类的无参构造方法。【隐藏一句代码:super()】
 如果非要执行父类带参构造方法的话,使用super(参数列表)
练习:JD商品
public class JD商品 {
private int 价格;
private String 品牌;

public int get价格() {
return 价格;
}
public void set价格(int 价格) {
this.价格 = 价格;
}
public String get品牌() {
return 品牌;
}
public void set品牌(String 品牌) {
this.品牌 = 品牌;
}

}
public class JD手机 extends JD商品 {

private String 质保期;
//-----------------------------------

public String get质保期() {
return 质保期;
}
public void set质保期(String 质保期) {
this.质保期 = 质保期;
}

} public class JD饮料 extends JD商品 {

private String 保质期;
//-----------------------------------

public void set保质期(String 保质期) {
this.保质期 = 保质期;
}

public String get保质期() {
return 保质期;
}
}
public class D0601继承 {
public static void main(String[] args) {
JD手机 _m = new JD手机();
_m.set品牌("诺基亚");
_m.set价格(199);
System.out.println(_m.get品牌());
System.out.println(_m.get价格());
}
}

重写
子类重新定义继承自父类的方法。

final(不准修改)
 Final修饰类:该类不可被继承(比如String类)
 Final修饰方法:该方法不能被重写
 Final修饰变量:不能被重新赋值
Java的“常量”
public static final int CHANG_LIANG = 10;
多态
父类对象指向子类实例;父类对象调用(多种)子类方法
底层技术:后期绑定(根据运行时期对象实例来动态判断要调用的函数)
Car a;
a = new 大黄蜂();
a.running();

a = new 御天敌();
//---此处略去3000行代码
a.running();

接口
 接口定义”做什么”---接口中,方法没有具体实现(没有{...})
 实现类定义”具体怎么做”---在实现类中,该方法必须被重写
public interface D0702洪七公 {
public void 降龙十八掌();
}
Java 只允许单继承,使用接口可以实现多重继承
public class D0702郭靖 extends D0702郭啸天 implements D0702洪七公, D0702江南七怪 {


@Override
public void 双枪() {
System.out.println("没学");
}

@Override
public void 降龙十八掌() {
System.out.println("郭靖版 降龙十八掌");
}

@Override
public void 基本功() {
System.out.println("基本功");
}
}

抽象类
含有抽象方法的类,必须声明为抽象类abstract
抽象类也是类,不能同时继承多个抽象类

接口继承接口
抽象类继承抽象类
接口没有构造方法
抽象类有构造方法
抽象类不能被实例化

集合和泛型
导包:import java.util.*;
ArrayList
Boy _Pan = new Boy();

Girl _g1 = new Girl();
Girl _g2 = new Girl();
Girl _g3 = new Girl();

List _泰国五日游 = new ArrayList();
_泰国五日游.add(_g1);
_泰国五日游.add(_g2);
_泰国五日游.add(_g3);
_泰国五日游.add(_Pan);

for (int i = 0; i < _泰国五日游.size(); i++) {
Girl g = (Girl)_泰国五日游.get(i);
}
代码没错,运行出错(对象本是Boy类型,偏要转成Girl类型---类型转换异常)
Exception in thread "main" java.lang.ClassCastException


ArrayList<E>使用泛型:指定列表内元素的类型
List<Girl> _泰国五日游 = new ArrayList<>();
_泰国五日游.add(_g1);
_泰国五日游.add(_g2);
_泰国五日游.add(_g3);
//提示代码有错误:_泰国五日游.add(_Pan);

Vector和ArrayList用法一致
元素超过它的初始大小 线程安全 效率
ArrayList *150% × 高
Vector *200% √ 低


LinkedList
addFirst() 头部添加
addLast() 尾部添加
removeFirst()
removeLast()

HashSet
Set<String> s = new HashSet<>();
s.add("A");
s.add("B");
s.add("C");
s.add("D");
boolean b是否为空 = s.isEmpty();
boolean b是否包含 = s.contains("A");
boolean b移除結果 = s.remove("A");
// foreach:遍历set
for (String str : s) {
System.out.println(str);
}
// 迭代器:遍历set
Iterator<String> it = s.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println("Iterator : " + str);
}


HashMap
存储K-V使用的是:key来区分
添加K-V对:put
删除:remove(Key)
查询:
1.containsKey
2.containsValue
遍历map
for (String _key : m.keySet()) {
System.out.println("key = " + _key);
System.out.println(" value = " + m.get(_key));
}
使用迭代器迭代map
Collection<String> values = m.values();
// 获得迭代器
Iterator<String> it = values.iterator();
while(it.hasNext()){
String next = it.next();
System.out.println(next);
}



HashTable(不接受null)
*不接受
*不提示
*运行时出错
// X m.put(null, "NNN");
// X m.put("NNN", null);


顺序 重复
List √ √
Set 输出有序(无序) 覆盖
Map 输出有序
(无序) key不重复(覆盖)

自定义泛型
class AH<E> {
E x;
}
<?>通配符
什么泛型都接收
import java.util.*;

public class D0803自定义泛型 {

public static void main(String[] args) {
List<String> lst1 = new ArrayList<>();
lst1.add("A");
lst1.add("B");
lst1.add("C");
printList(lst1);


List<Integer> lst2 = new ArrayList<>();
lst2.add(1);
lst2.add(2);
lst2.add(3);
printList(lst2);
}

// <?> : 通配符
static void printList(List<?> lst2){
for (Object integer : lst2) {
System.out.println(integer);
}
}
}
*<? extends/super Person>
?表示只有继承自Person的类型是合法类型
<? extends Person>:定义参数
<? super Person>:定义变量/返回类型
import java.util.*;

public class D0803自定义泛型 {

public static void main(String[] args) {
List<Boy> lst1 = new ArrayList<>();
printList(lst1);

List<Girl> lst2 = new ArrayList<>();
printList(lst2);

List<String> lst3 = new ArrayList<>();
//String 没有继承Person,代码报错 printList(lst3);

List<? super Person> lst = new ArrayList<>();
lst.add(new Boy());
lst.add(new Girl());
//String 没有继承Person,代码报错 lst.add("A");
}

// <?> : 通配符
static void printList(List<? extends Person> lst2){
for (Object integer : lst2) {
System.out.println(integer);
}
}
}

class Person{
}
class Boy extends Person{
}

class Girl extends Person {
}

扩展:集合排序

package ah.day09;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class 集合扩展 {

// 1.调用Collections.sort(lst);
// 2.要排序的类型,必须implements Comparable<自身类型>
// 3.实现方法:compareTo() return 正(升序)/负(降序)
public static void main(String[] args) {
Phone p = new Phone(2299, 57000);
List<Phone> lst = new ArrayList<Phone>();
lst.add(p);

p = new Phone(1099, 260000);
lst.add(p);

p = new Phone(1299, 380000);
lst.add(p);

// Collection
Collections.sort(lst);

for (Phone ph : lst) {
System.out.println("价格:" + ph.getPrice() + " --- 销量:"
+ ph.getCount());
}
}
}

// -----------------------------------------
class Phone implements Comparable<Phone> {
private double price;
private int count;

public double getPrice() {
return price;
}

public int getCount() {
return count;
}

public Phone(double price, int count) {
super();
this.price = price;
this.count = count;
}

@Override
public int compareTo(Phone o) {
// this VS o(other)
if (this.price > o.price) {
// 返回正数:升序
return 10;
} else {
// 返回负数:降序
return -10000000;
}
}
}

多种方式排序
 Collections.sort(參數1:列表 參數2:比較器)
 定义比较器类:implements Comparator<Phone>
package ah.day09;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class 集合扩展 {

// 1.调用Collections.sort(lst);
// 2.要排序的类型,必须implements Comparable<自身类型>
// 3.实现方法:compareTo() return 正(升序)/负(降序)
public static void main(String[] args) {
Phone p = new Phone(2299, 57000);

List<Phone> lst = new ArrayList<Phone>();
lst.add(p);

p = new Phone(1099, 260000);
lst.add(p);

p = new Phone(1299, 380000);
lst.add(p);

// Collection
Collections.sort(lst);

for (Phone ph : lst) {
System.out.println("价格:" + ph.getPrice() + " --- 销量:"
+ ph.getCount());
}
System.out.println("-----------------銷量降序排列---------------");
// 按銷量降序(參數1:列表 參數2:比較器)
Collections.sort(lst, new CountDesc());
for (Phone ph : lst) {
System.out.println("价格:" + ph.getPrice() + " --- 销量:"
+ ph.getCount());
}
}
}

// -----------------------------------------
class Phone implements Comparable<Phone> {
private double price;
private int count;

public double getPrice() {
return price;
}

public int getCount() {
return count;
}

public Phone(double price, int count) {
super();
this.price = price;
this.count = count;
}

@Override
public int compareTo(Phone o) {
// this VS o(other)
if (this.price > o.price) {
// 返回正数:升序
return 10;
} else {
// 返回负数:降序
return -10000000;
}
}
}

// --------------
class CountDesc implements Comparator<Phone> {

@Override
public int compare(Phone o1, Phone o2) {
return (o1.getCount() > o2.getCount()) ? -1 : 1;
}
}

常用包
java.lang

包装类

原始数据类型 包装类
boolean(布尔型) Boolean
byte(字节型) Byte
char(字符型) Character
short(短整型) Short
int(整型) Integer
long(长整型) Long
float(浮点型) Float
double(双精度浮点型) Double

Math
Math.random()
java.util
Random

Random r = new Random();
for(int i = 0;i<10;i++){
System.out.println(r.nextInt(101));//0-100的随机整数
}


Date
Date d = new Date(1,6,1);
Calendar
// Calendar是抽象类,不能new
Calendar c = Calendar.getInstance();
// 精确添加添加(年,月,日)
c.add(Calendar.DATE, 49);// 49天之后的日期

// 获取年月日信息(月从0开始)
int i = c.get(Calendar.YEAR);
System.out.println(i);

// 设置具体日期(new Date(int year, int month, int date)的替代物)
c.set(2017, 8,1);

// 转成Date
Date time = c.getTime();
System.out.println(time);


异常
Try{尝试执行}
Catch{出错时执行}
Finally{出不出错都执行,在return之前执行}
public class D0905异常 {
public static void main(String[] args) {
int a = 10, b = 1;
TestException(a, b);
}
static boolean TestException(int a, int b){
try{
System.out.println(a/b);
}catch(ArithmeticException e){// 声明,此处可能抛出"算术异常"
System.out.println("系统维护中,请稍后重试");
return false;
}finally{
System.out.println("---END---");
}
return true;
}
}

自定义异常throw
自定义异常类,继承Excption类
一般需要写一个带参构造方法

public class D0906自定义异常 {

public static void main(String[] args) {
int a = 10;
TestException(a);
}
static boolean TestException(int money){
try{
if (money < 10000){
// 拋一個異常對象
throw new DidiException("系統升級,請半年后重試");
}
}catch(Exception e){// 声明,此处可能抛出"算术异常"

e.printStackTrace();

return false;
}finally{
System.out.println("---END---");
}
return true;
}
}

class DidiException extends Exception{
public DidiException(String message){
super(message);
}
}


IO

File类

File f = new File("AhLog.txt");// 相对路径,相对于整个程序的根目录
File f2 = new File("D:/AhLog.txt");// 绝对路径
File f3 = new File("D:");// 文件夾

boolean _文件是否存在 = f.exists();
boolean _是文件夹吗 = f.isDirectory();
boolean _是文件吗 = f.isFile();
String _文件名 = f.getName();
String _文件全名 = f.getAbsolutePath();
long _修改时间 = f.lastModified();

文件扫描(递归)


static void 递归查找文件(String path){
File f = new File(path);
System.out.println("------开始查找["+path+"]----------");
// 获取文件夹下所有的文件(包括文件夹)
File[] fs = f.listFiles();
for (File file : fs) {
//
if (file.isDirectory()){
递归查找文件(file.getAbsolutePath());
}else{
System.out.println(file.getAbsolutePath());
}
}
}
调用:
public static void main(String[] args) {
递归查找文件("D:");
}
字节流

FileInputStream/FileOutputStream

优点:处理文件效率高.
缺点:一个字节一个字节地处理,对应中文可能出现乱码.

例:文件复制(从文件a读入字节流,直接输出到文件b)

static void CopyFile(String a, String b) {
try {
FileInputStream fis = new FileInputStream(a);
FileOutputStream fos = new FileOutputStream(b);
byte[] buffer = new byte[2048];
while (true) {
int read = fis.read(buffer);
if (read == -1){
break;
}
fos.write(buffer);
}

fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("----------END--------------");
}


字符流
专门应对字符
static void 读文件() {
try {
FileReader fr = new FileReader("D:\\abc.txt");
BufferedReader br = new BufferedReader(fr);

String s;
while (true) {
s = br.readLine();
if (s == null) {// 没读到数据(文件完了)
break;
}
System.out.println(s);
}

br.close();
fr.close();

} catch (IOException e) {
e.printStackTrace();
}
}

static void 写文件() {
try {
FileWriter fw = new FileWriter("D:\\abc2.txt");
BufferedWriter bf = new BufferedWriter(fw);
bf.write("どうぞ よろしく お愿いします");

bf.close();
fw.close();

} catch (IOException e) {
e.printStackTrace();
}
}
序列化
使一个类可被序列化,需要两步:
1.implements Serializable
2.生成序列号:
消除警告,权宜之计 private static final long serialVersionUID = 1L;
有代码版本识别功能
 修改类的代码,删除序列号
 再生成就是新的序列号 private static final long serialVersionUID = 5772255382967012814L;

transient 修饰的变量,不会被序列化

序列化 示例:将(new)对象序列化到文件中
反序列化 示例:再从文件中读出对象
package ah.day11;

import java.io.*;

public class D1101序列化 {

public static void main(String[] args) throws Exception {
序列化();
反序列化();
}

// 把对象写到文件中
static void 序列化() throws IOException {
Dog g = new Dog();
g.setName("tolangpu");

File f = new File("D:\\obj.txt");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(g);

oos.close();
fos.close();
}

// 从文件读出对象
static void 反序列化() throws Exception {
File f = new File("D:\\obj.txt");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
Dog obj = (Dog) ois.readObject();
System.out.println(obj);

ois.close();
fis.close();
}

}

class Dog implements Serializable {
// 序列号
// private static final long serialVersionUID = -5623386584421135084L;

private static final long serialVersionUID = 5772255382967012814L;

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

void m() {
System.out.println("汪");
}

}



多线程

第一个线程
public static void main(String[] args) {
Thread currentThread = Thread.currentThread();
System.out.println(currentThread);
}

Java线程编码方式
继承Thread类
重写run方法
实例化该对象,并调用start()方法.
示例代码说明:为了延长线程执行时间,在for循环内加Thread.sleep(毫秒)方法
public class D1104多线程 {

public static void main(String[] args) throws InterruptedException {

MyThread t = new MyThread();
// t.run();
t.start();

for (int i = 0; i < 100; i++) {
Thread.sleep(50);
System.out.println("寫作業");
}
}
}

class MyThread extends Thread {

@Override
public void run() {
System.out.println(Thread.currentThread());
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" 聽歌");
}
}

}

实现runnable接口
还是要用到Thread类,
还是要使用start()启动线程,
还是要重写run方法.
只不多需要多实例化一个对象.
package ah.day11;

public class D1105多线程R {

public static void main(String[] args) {
MyThreadR r = new MyThreadR();
Thread t = new Thread(r);
t.start();

for (int i = 0; i < 100; i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("写作业");
}
}
}

class MyThreadR implements Runnable {

@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" 听音乐");
}
}
}


线程的优先级
t.setPriority(Thread.MAX_PRIORITY); // 10
t.setPriority(Thread.NORM_PRIORITY); // 默认都是普通优先级 5
t.setPriority(Thread.MIN_PRIORITY); // 1

线程状态
新建(new)
就绪(start())
运行(run()ing)
死亡(run(执行完毕))
阻塞 等待/阻塞/睡眠

Sleep() And interrupt()方法
Thread.sleep(1000);//睡1s,记得加try catch
尽量不要使用interrupt()打断睡觉的线程
Yield()方法:
礼不下庶人
暂停当前正在执行的线程对象,让其他线程执行(只让位给优先级相同或更高的线程)
package ah.day11;

public class D1108Yield {

public static void main(String[] args) {
Thread t1 = new MyThread08();
t1.setName("1");
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();

Thread t2 = new MyThread08();
t2.setName(" 2");
t2.start();
}
}

class MyThread08 extends Thread {
@Override
public void run() {
String name = currentThread().getName();
int p = currentThread().getPriority();

for (int i = 0; i < 100; i++) {
if (i % 10 == 0) {

System.out.println(name + ":" + p + " i= " + i + " yield");
yield();
} else {
System.out.println(name + ":" + p + " i= " + i);
}
}
}
}

Join()方法:
通俗:等我做完
等待该线程执行完毕
package ah.day11;

public class D1109 {

public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread09();
t.start();

for (int i = 0; i < 10; i++) {
if (i == 5) {
// 等待线程t做完
t.join();
}

Thread.sleep(100);

System.out.println(Thread.currentThread().getName() + " : " + i);
}
}

}

class MyThread09 extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(" " + currentThread().getName() + " : " + i);
}
}
}


线程同步
package ah.day11;

public class D1110取钱 {

public static void main(String[] args) {
Runnable r = new 取钱();
Thread _User = new Thread(r,"持卡人");
_User.start();
Thread _thief = new Thread(r,"贼");
_thief.start();

}


}
// 线程同步
class 取钱 implements Runnable{
private int money=1000;
public void whithDraw(){
String name = Thread.currentThread().getName();
synchronized (this) {//同步代码块
if (money >= 1000) {
System.out.println(name + "取钱中...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
money -= 999;
System.out.println(name + "取钱完毕,您的余额是:¥" + money);
}else{
System.out.println(name+" 余额不足");
}
}
}
@Override
public void run() {
whithDraw();
}

}

另一种线程同步方式(对方法加线程同步,该方法同一时间,只能被一个线程调用)
public synchronized void whithDraw(){}
卖票
1.实现runnable接口
package ah.day12;

//1.实例化一个Runnable对象
//2.main方法中,仅实例化一个Runnable对象
//3.main方法中,开3个线程
public class D1201卖票 {

public static void main(String[] args) {
Runnable r = new 卖票();

Thread t1 = new Thread(r, "窗口1");
Thread t2 = new Thread(r, "窗口2");
Thread t3 = new Thread(r, "窗口2");

t1.start();
t2.start();
t3.start();
}
}

class 卖票 implements Runnable {
private int tickts = 100;

private void sell() {
while (true) {
synchronized (this) {// 锁住:Runnable r = new 卖票();
if (tickts > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("卖出第" + tickts + "张票");
tickts--;// tickts = tickts -1 // tickts-=1;
} else {
break;
}
}
}
}

@Override
public void run() {
// 卖票
sell();
}

}
2.继承Thread类
package ah.day12;

//如果卖票的对象new了3次
//1.票数必须是static的(保证在系统中的唯一性)
//2.无中生有,造一个Object对象(保证其唯一性),锁的时候就锁这个对象
public class D1201卖票extendsThread {

public static void main(String[] args) {

Thread t1 = new 卖票2();
Thread t2 = new 卖票2();
Thread t3 = new 卖票2();

t1.start();
t2.start();
t3.start();

}
}

class 卖票2 extends Thread {
private static int tickts = 100;
private static Object obj = new Object();

private void sell() {
while (true) {
synchronized (obj) {
if (tickts > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("卖出第" + tickts + "张票");
tickts--;// tickts = tickts -1 // tickts-=1;
} else {
break;
}
}
}
}

@Override
public void run() {
// 卖票
sell();
}
}







后台线程(守护线程)
守护线程一定要在start前开启
前台线程接受,守护线程就结束
package ah.day13;

public class D1301守护线程 {

public static void main(String[] args) throws InterruptedException {
MyThread1301 t = new MyThread1301();
t.setDaemon(true);
t.start();


for (int i = 0; i < 30; i++) {
Thread.sleep(100);
System.out.println(i);
}
}
}

class MyThread1301 extends Thread {
@Override
public void run() {
for (int i = 0;; i++) {
if (i % 100 == 0) {
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("-----------守护----" + i);
}
}
}
}


网络编程

控制台运行Socket
1. 前提:.class文件已经生成(现再MyEclipse中跑一次,注意关闭程序)
2. 进入bin文件夹,左手按Shift,在空白处右键选择”在此处打开命令窗口”
3. 输入java 包名.类名
4. 回车
查看端口使用情况
查看端口使用情况:
netstat -ano
-a 显示所有连接和监听端口。
-n 以数字形式显示地址和端口号。 此选项可以与 -a选项组合使用
-o 显示与每个连接相关的所属进程 ID。

精确查看端口
netstat -ano|findstr "8848"

查看进程
tasklist|findstr "11044"



字符流(发消息)
package ah.day14;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class D1403SocketMultiThread {
public static final int PORT = 8850;

public static void main(String[] args) {
Thread t = new IpMsgServce();
t.start();

(new IpMsgClient()).start();

}
}

/**
* 服务器
*
* @author Administrator
*
*/
class IpMsgServce extends Thread {
private void myServer() throws IOException {
// 服务器Socket
ServerSocket ss = new ServerSocket(D1403SocketMultiThread.PORT);

// 通讯用的socket
Socket s = null;

while ((s = ss.accept()) != null) {
// 读入请求
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

String str = br.readLine();
InetAddress ip = s.getInetAddress();
String hostAddress = ip.getHostAddress();
System.out.println(hostAddress + "说:" + str);

br.close();
isr.close();
is.close();
// 通讯用的socket对象,必须关闭
s.close();
}

ss.close();

}

@Override
public void run() {
try {
myServer();
} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* 客户端
*
* @author Administrator
*
*/
class IpMsgClient extends Thread {
private void myClient() throws IOException {

Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入对方IP:");
String toIp = sc.nextLine();
Socket s = new Socket(toIp, D1403SocketMultiThread.PORT);

// 发送消息
OutputStream os = s.getOutputStream();
PrintWriter pr = new PrintWriter(os);

System.out.println("请输入要说的话:");
String str = sc.nextLine();

pr.println(str);
pr.flush();

pr.close();
os.close();

s.close();
}

}

@Override
public void run() {
try {
myClient();
} catch (IOException e) {
e.printStackTrace();
}
}
}



字节流(发文件)
客户端:读入文件, 输出Stream
package ah.day14;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class D1404FileS {

public static void main(String[] args) throws IOException {
byte[] bs = new byte[2048];
ServerSocket ss = new ServerSocket(8848);
Socket s = ss.accept();

// 取文件名(字符流,方便取文件名)
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String fileName = br.readLine();

// 以下操作为字节流(效率高)
FileOutputStream fos = new FileOutputStream("C:\\" + fileName);
while (true) {
// 收消息(InputStream)
int ret = is.read(bs);
if (ret == -1) {
System.out.println("接收完毕");
s.close();
return;
}

// 写文件(OutputStream)
fos.write(bs, 0, ret);
}
}

}



服务器:读入Stream, 输出文件
package ah.day14;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

public class D1404FileC {

public static void main(String[] args) throws IOException {
byte[] bs = new byte[2048];
Socket s = new Socket("127.0.0.1", 8848);

// 先发送文件名(字符流,方便取文件名)
File f = new File("D:\\baidu.png");
OutputStream os = s.getOutputStream();
PrintWriter pr = new PrintWriter(os);
pr.println(f.getName());
pr.flush();

// 读入文件(InputStream)
FileInputStream fis = new FileInputStream(f);
while (true) {
int ret = fis.read(bs);
if (ret == -1) {
System.out.println("发送完毕");
s.close();
return;
}

// 发送信息(OutputStream)
os.write(bs, 0, ret);
}

}

}


Junit
单元测试

JDBC
导入外部jar包
项目->右键->Build Path(构建路径)->Add External Archives...(010瓶)



Jar包导入后认的是绝对路径,如果jar包位置改变,需要修改:
项目->右键->Build Path(构建路径)->Configure Build Path...

->重新编辑(Edit)jar包的路径



基本SQL语句
查 SELECT * FROM testuser

查询全部 ResultSet rs = ps.executeQuery();
返回的是结果集
SELECT * FROM testuser
WHERE uname ='Dog' AND pwd='123'

登录(根据用户名和密码查询用户数据)
增: 插入新数据(id自增长,不管) INSERT INTO testuser
(uname, pwd)
VALUES
('Andy', '1') int ret = ps.executeUpdate();
返回的是受影响行数
删: 根据用户名删除数据 DELETE FROM testuser
WHERE uname='Andy'
改: 根据用户名修改密码 UPDATE testuser SET pwd='9' WHERE uname='Andy'

模拟用户登录
package ah.day15;

import java.sql.*;
import java.util.Scanner;

public class D1501JDBC {

public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

public static void main(String[] args) throws ClassNotFoundException,
SQLException {

// 加载数据库驱动
Class.forName(DRIVER);

// 获取数据库链接
Connection conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);

// 创建语句
Statement sta = conn.createStatement();

String sUname, sPwd;
{
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
sUname = sc.nextLine();

System.out.println("请输入密码:");
sPwd = sc.nextLine();
}

String sql = "SELECT * FROM testuser WHERE uname ='" + sUname + "' AND pwd='" + sPwd + "'";
System.out.println(sql);
ResultSet rs = sta.executeQuery(sql);// 语句.执行询问();

if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}

// 关闭连接
rs.close();
sta.close();
conn.close();
}
}

SQL注入,绕过登录验证:
请输入用户名:
Dog'--
请输入密码:
1
SELECT * FROM testuser WHERE uname ='Dog'-- ' AND pwd='1'
登录成功


使用preparedStatement防止SQL注入
package ah.day15;

import java.sql.*;
import java.util.Scanner;

public class D1502JDBCPrepSat {

public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

public static void main(String[] args) throws ClassNotFoundException,
SQLException {

String sUname, sPwd;
{
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
sUname = sc.nextLine();

System.out.println("请输入密码:");
sPwd = sc.nextLine();
}

// 加载数据库驱动
Class.forName(DRIVER);

// 获取数据库链接
Connection conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);

// 创建语句
PreparedStatement ps = conn.prepareStatement("SELECT * FROM testuser WHERE uname = ? AND pwd=?");// 预编译
ps.setString(1, sUname);
ps.setString(2, sPwd);

ResultSet rs = ps.executeQuery();

if (rs.next()) {
System.out.println("登录成功");
} else {
System.out.println("登录失败");
}

// 关闭连接
rs.close();
ps.close();
conn.close();
}
}

JDBC的事务处理
package ah.day15;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class D1504RollBack {
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

private static Connection conn;

public static void main(String[] args) {
// 获取数据库链接
try {
conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);
// 1.设置手动提交
conn.setAutoCommit(false);

String sql = "INSERT INTO testuser (uname, pwd) VALUES ('Andy', '1')";
PreparedStatement ps = conn.prepareStatement(sql);// 预编译
ps.executeUpdate();

System.out.println(1 / 0);

sql = "INSERT INTO testuser (uname, pwd) VALUES ('Bob', '1')";
ps = conn.prepareStatement(sql);// 预编译
ps.executeUpdate();

} catch (SQLException e) {
System.out.println("出现异常");
// 3.回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}

// 2.提交
try {
conn.commit();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}

}

}


DAO,DataAccessObject,数据访问对象
1. 创建基类(BaseDao.java)
1.1 写常量
1.2 定义成员变量:Connection,PreparedStatment,ResultSet
1.3 定义方法: 获取连接, 关闭连接
2. 创建子类Dao
2.1 继承BaseDao
2.2 super.打开连接()
2.3 创建语句
2.4 执行语句
2.5 关闭连接(finally)
3.在单独的类里创建main方法测试

package ah.day16;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// 所有 D数据A访问O对象 的基类
public class BaseDao {
public static final String DRIVER = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://192.168.4.120:3306/test";
public static final String USER_NAME = "root";
public static final String USER_PWD = "root";

protected Connection conn = null;
protected PreparedStatement ps = null;
protected ResultSet rs = null;

/**
* 获取连接
*
* @throws SQLException
*/
void getConn() {

try {
// 加载数据库驱动
Class.forName(DRIVER);

// 获取数据库链接
conn = DriverManager.getConnection(URL, USER_NAME, USER_PWD);

} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}

/**
* 关闭连接
*/
void closeConn() {
try {

if (rs != null) {
rs.close();
rs = null;
}

if (ps != null) {
ps.close();
ps = null;
}

if (conn != null) {
conn.close();
conn = null;
} else {
// 如果conn ≠ null
// do nothing
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

package ah.day16;

import java.sql.ResultSet;
import java.sql.SQLException;

public class D1602MoviesDao extends BaseDao {
/**
* 查询电影的票价
*
*/
public double getMovies() {

try {
// 1.获取连接
super.getConn();// super. 可省略
// 2.创建语句
ps = conn.prepareStatement("SELECT * FROM movies WHERE mname = ?");
ps.setString(1, "战狼");

rs = ps.executeQuery();
if (rs.next()) {
double price = rs.getDouble("price");
return price;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}

// 没取到的时候
return 0.0;
}

public ResultSet getAllMovies() {

try {
// 1.获取连接
super.getConn();// super. 可省略
// 2.创建语句
ps = conn.prepareStatement("SELECT * FROM movies");

rs = ps.executeQuery();

return rs;
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}

return null;
}

}

测试: 类名略
public static void main(String[] args) throws ClassNotFoundException,
SQLException {
D1602MoviesDao dao = new D1602MoviesDao();
double price = dao.getMovies();
// 在调用方打印查询结果
System.out.println(price);
}


注意事项:
1.尽量不要用SELECT * FROM 表,把*换成具体的数据库表的列名,中间用逗号分隔,比如:
SELECT
id,
price
FROM
movies
2.使用StringBuilder拼接SQL语句,注意前后都加上一个空格
StringBuilder sb = new StringBuilder();
sb.append(" SELECT ");
sb.append(" id, ");
sb.append(" price ");
sb.append(" FROM ");
sb.append(" movies ");
sb.append(" WHERE ");
sb.append(" mname = ? ");
ps = conn.prepareStatement(sb.toString());

使用List取多条数据对象
1.创建POJO(简单JAVA对象)
1.1 主要包括私有成员变量和get/set方法
1.2 成员变量和数据库中的字段保持一致
2.编写Dao中的方法
2.1 从ResultSet中取出结果,
2.2 实例化(new)POJO类的对象
2.3 将”2.1”取到的结果设置到”2.2”的对象中
2.4 将POJO类的对象add到返回的List中

1.创建POJO(简单JAVA对象)
package ah.day16;

/**
* 贿赂类(JavaBean,POJO)
*
* @author Administrator
*
*/
public class Bribe {

public Bribe(int id, String who, String when, String how, String what,
String howmuch) {
super();
this.id = id;
this.who = who;
this.when = when;
this.how = how;
this.what = what;
this.howmuch = howmuch;
}

private int id;
private String who;
private String when;
private String how;
private String what;
private String howmuch;
// get set方法略
}

2.编写Dao中的方法
BaseDao.java略
package ah.day16;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class D1602MoviesDao extends BaseDao {

// public ResultSet getAllMovies() {
public List<Bribe> getAll受贿记录() {

List<Bribe> lst = new ArrayList<Bribe>();
try {
// 1.获取连接
super.getConn();// super. 可省略
// 2.创建语句
ps = conn.prepareStatement("SELECT * FROM bribe");

rs = ps.executeQuery();
while (rs.next()) {
int _id = rs.getInt("id");
String _who = rs.getString("who");
String _when = rs.getString("when");
String _how = rs.getString("how");
String _what = rs.getString("what");
String _howmuch = rs.getString("howmuch");
Bribe b = new Bribe(_id, _who, _when, _how, _what, _howmuch);

lst.add(b);
}
return lst;
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}

return null;
}

}


package ah.day16;

import java.sql.*;
import java.util.List;

/**
* 调用方:处理业务逻辑
*
* @author Administrator
*
*/
public class D1601Test {

public static void main(String[] args) throws ClassNotFoundException,
SQLException {

// 1.实例化DAO对象
D1602MoviesDao dao = new D1602MoviesDao();

// 2.把数据取出来
List<Bribe> all受贿记录 = dao.getAll受贿记录();

// 3.处理数据
for (Bribe b : all受贿记录) {
System.out.println(b.getWho() + ":" + b.getHowmuch());
}
}
}

Batch
不同点:
preparedStatment只能执行一种SQL语句,参数可以不同
Statement可以执行任意的一批不同的SQL语句
相同点:
.addBatch()
执行都使用:int[] executeBatch = ps.executeBatch();



存储过程
MySQL存储过程
DROP PROCEDURE
IF EXISTS findpwd;

CREATE PROCEDURE findpwd (
IN iname VARCHAR (20),
OUT opwd VARCHAR (20)
)
BEGIN
SELECT
pwd INTO opwd
FROM
customer
WHERE
uname = iname;


END

MySQL调用存储过程
SET @iname='Andy';
CALL findpwd(@iname,@opwd);
SELECT @opwd

JAVA调用存储过程
输出型的参数需要注册,执行之后可以取值
package ah.day16;

import java.sql.CallableStatement;
import java.sql.SQLException;

public class D1604Prod extends BaseDao {
public static void main(String[] args) {
new D1604Prod().testProd();
}

public void testProd() {

try {
getConn();
CallableStatement cs = conn.prepareCall("call findpwd(?,?)");
cs.setString(1, "我爱你");// 输入型参数
// java.sql.Types.INTEGER
cs.registerOutParameter(2, java.sql.Types.VARCHAR);// 输出型参数(1.注册)

cs.executeQuery();
String pwd = cs.getString(2);// 输出型参数(2.取值)
System.out.println(pwd);
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeConn();
}
}
}




练习:
创建
DROP PROCEDURE
IF EXISTS proc1;
CREATE PROCEDURE `proc1`(in var1 int, out var2 int)
BEGIN
set var2= var1+1;
END
调用(--注释在Workbench中无效,只能用#注释)
set @var1 = 10; #输入参数
set @var2 =10; #输出参数
CALL proc1(@var1, @var2);
select @var2 #查看输出参数

反射
获取私有的构造方法
package ah.day17;

public class Dog {

// ---private-----------------
private Dog() {
System.out.println("Dog 对象被创建");
}

private void m(String s) {
System.out.println("旺旺:" + s);
}

// ---public-----------------
public Dog(String name) {
System.out.println("Dog:" + name + " 对象被创建");
}

public void m() {
System.out.println("旺旺!");
}
}

package ah.day17;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class D1701反射调用方法 {

public static void main(String[] args) throws Exception {
// new Dog();

// Class<?> forName1 = String.class;
// System.out.println(forName1);
//
// Class<?> forName2 =Class.forName("java.lang.String");
// System.out.println(forName2);
// 1.获取类
Class<?> forName = Class.forName("ah.day17.Dog");

// 2.获取构造方法
// Constructor<?>[] declaredConstructors =
// forName.getDeclaredConstructors();// 获取私有的构造方法
Constructor<?> cs = forName.getDeclaredConstructor();
cs.setAccessible(true);

// 2.1 实例化对象(new)
Object obj = cs.newInstance();
Dog d = (Dog) obj;
System.out.println(d);

// 3.获取私有方法
Method m = forName.getDeclaredMethod("m", String.class);
m.setAccessible(true);
m.invoke(obj, "牛奶");
}
}

读取配置文件创建对象/调用方法
配置文件config.properties
className=ah.day17.Dog
methodName=m

Java代码
package ah.day17;

import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

public class D1702配置文件创建对象 {

public static void main(String[] args) throws IOException {

Properties p = new Properties();
// 1.读入配置文件
FileReader _fileReader = new FileReader("src/config.properties");
p.load(_fileReader);
_fileReader.close();

// 2.操作配置信息
String className = p.getProperty("className", "默认值,取不到数据时的值");

String methodName = p.getProperty("methodName", "");
System.out.println(className + ":" + methodName);

// 3.创建对象,并调用方法
createClassAndExeMethod(className, methodName);
}

public static void createClassAndExeMethod(String className,
String methodName) {
try {
Class<?> cls = Class.forName(className);
Constructor<?> cs = cls.getConstructor(String.class);
Object obj = cs.newInstance("哈士奇");

Method m = cls.getMethod("m");
m.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}

}



设计模式
类的关系
继承
UML类图设计中,继承用一条带空心三角箭头的实线表示,从子类指向父类,或者子接口指向父接口

实现
在UML类图设计中,实现用一条带空心三角箭头的虚线表示,从类指向实现的接口

依赖
简单的理解,依赖就是一个类A使用到了另一个类B
这种使用关系是偶然的、临时性的、非常弱的
类B的变化会影响到类A
代码层面,表现为类B作为参数被类A在某个method方法中使用
UML类图设计中,依赖关系用由类A指向类B的带箭头虚线表示

class A
{
public void Method(依赖B b)
{
}
}
class 依赖B
{
}
关联
关联是语义级别的一种强依赖关系
关联可以是单向、双向的
表现在代码层面,为被关联类B以类的属性形式出现在关联类A中
UML类图设计中,关联关系用由关联类A指向被关联类B的带箭头实线表示,在关联的两端可以标注关联双方的角色和多重性标记

class A
{
private 关联B myVar;
public 关联B MyProperty
{
get { return myVar; }
set { myVar = value; }
}
}
class 关联B
{
}
组合(合成) ·聚合
组合也是关联关系的一种特例
体现的是一种contains-a的关系
也称为强聚合
表现在代码层面,和关联关系是一致的,只能从语义级别来区分
UML类图设计中,组合关系以实心菱形加实线箭头表示

组合示例:人由大脑.心脏等组成

聚合是关联关系的一种特例
是整体与部分的关系,即has-a的关系
表现在代码层面,和关联关系是一致的,只能从语义级别来区分
UML类图设计中,聚合关系以空心菱形加实线箭头表示

聚合示例:孩子和家庭/人和人群


设计六原则
开闭原则(核心)
(Open Close Principle)
理论:对扩展开放,对修改关闭(Open for extension)
实践:尽量使用接口和抽象类(Cloded for modification)

里氏代换原则
(Liskov Substitution Principle, LSP)
理论:父类可以出现的地方,子类一定可以出现
父类替换成子类,程序的行为没有变化,所以父类可以代表任何子类---体现其可重用性
实践:以父类名义声明子类对象

依赖倒转原则(基础)
(Dependence Inversion Principle)
理论:抽象不应该依赖细节,细节应该依赖抽象---即对接口编程,而不是对实现编程.

接口隔离原则
(Interface Segregation Principle)
理论:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

迪米特法则(最少知道原则)(Demeter Principle)
理论:各模块尽量独立


合成复用原则(Composite Reuse Principle)
理论:尽量使用合成/聚合的方式,而不是使用继承(继承毕竟有耦合,父类改了子类就要改)。
实践:Business层调用Dao层,有一个Dao对象的变量,而不是继承Dao

单例模式
1. 懒汉式(第一次用的时候加载.怕被抢,需要线程同步,因此影响效率)
2. 饿汉式(猴急,占了不用)
(比如调了该类的其他static方法,其单例对象也会加载;而其他方式此类情况单例对象不加载)
3. 综合式(使用静态内部类,调用该类属于懒汉(不占用),该类里面属于饿汉,调用即加载)
效果上类似懒汉,但是无需线程同步
/**
* 1.私有的 实例对象 2.私有的 构造方法 3.公开化 获取实例(getInstance)
*/
public class Single {
public static void main(String[] args) {
Lazy.getInstance();
System.out.println("-----------");
Hungry.getInstance();
System.out.println("-----------");
Singleton.getInstance();
}
}

class Lazy {
private static Lazy instance;

private Lazy() {
System.out.println("懒汉");
}

public static synchronized Lazy getInstance() {
System.out.println("Lazy getInstance");
// 用时加载,影响性能(要做线程同步)
if (instance == null) {
instance = new Lazy();
}
return instance;
}

}

class Hungry {
// 立马加载,闲置资源(很多类都这么干的时候)
private static Hungry instance = new Hungry();

private Hungry() {
System.out.println("饿汉");
}

public static Hungry getInstance() {
System.out.println("Hungry getInstance");
return instance;
}
}

class Singleton {
// 化实例对象为静态内部类
// 用时建类,建类加载
// 不浪费,无同步
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}

private Singleton() {
System.out.println("静态内部类");
}

public static Singleton getInstance() {
System.out.println("Singleton getInstance");
return Holder.INSTANCE;
}
}

简单工厂模式
package designpattern.bean;
public abstract class Car {
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}

public abstract void drive();
}
package designpattern.bean;
public class Benz extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}
package designpattern.bean;
public class Bmw extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}

根据字符串,创建类
package designpattern;
import designpattern.bean.*;
public class C简单工厂 {
public static void main(String[] args) {
Car car = FactoryS.createCar("benz");
car.setName("benz");
car.drive();
}
}

class FactoryS {
public static Car createCar(String car) {
Car c = null;
if ("Benz".equalsIgnoreCase(car))
c = new Benz();
else if ("Bmw".equalsIgnoreCase(car))
c = new Bmw();
return c;
}
}



工厂模式
工厂和简单工厂相比,工厂有了扩展,有了统一的规范
工厂模式:定义一个创建对象的接口,但由子类决定实例化哪一个,工厂方法的实例化推迟到了子类。

package designpattern;

import designpattern.bean.*;

public class C工厂 {
public static void main(String[] args) throws Exception {
FactoryAbs d = new BenzFactory();
Car c = d.createCar();
c.setName("benz");
c.drive();
}
}

// 抽象工厂
abstract class FactoryAbs {
public abstract Car createCar() throws Exception;
}

class BenzFactory extends FactoryAbs {
public Car createCar() throws Exception {
return new Benz();
}
}

class BmwFactory extends FactoryAbs {
public Car createCar() throws Exception {
return new Bmw();
}
}




抽象工厂模式
---提供一个接口,用于创建相关和依赖对象的家族,而不需要指定具体类。

工厂模式的优点:
1.工厂方法封装了对象创建的细节,将对象创建代码和其他部分脱离,减少相干性.
2.有利于同类对象创建的统一管理和控制
3.你所关心的仅仅是工厂方法返回的接口方法,不必关心实现细节

抽象工程和工厂相比,制造业升级!能制造产品2了

package designpattern;

import designpattern.bean.*;

public class C抽象工厂 {
public static void main(String[] args) throws Exception {
// 找奔驰工厂
AbstFactory f = new BenzFactory2();
// 造车造体育馆随意
Arena arena = f.createArena();
arena.setName("Mercedes Benz");
arena.logo();
}
}

// 抽象产品(竞技场)
abstract class Arena {
private String name;

public abstract void logo();

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

// 具体产品(Bmw和Audi同理)
class BenzArena extends Arena {

@Override
public void logo() {
System.out.println(this.getName());
}
}

class BmwArena extends Arena {
@Override
public void logo() {
System.out.println(this.getName());
}
}

// 抽象工厂
abstract class AbstFactory {// brand:品牌
public abstract Car createCar() throws Exception;

public abstract Arena createArena() throws Exception;
}

// 具体工厂
class BenzFactory2 extends AbstFactory {

@Override
public Car createCar() throws Exception {
return new Benz();
}

@Override
public Arena createArena() throws Exception {
return new BenzArena();
}

}

class BmwFactory2 extends AbstFactory {

@Override
public Car createCar() throws Exception {
return new Benz();
}

@Override
public Arena createArena() throws Exception {
return new BenzArena();
}
}

适配器模式
痛点: 一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的
实例: 美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V

package adapter;

public class C适配器 {
public static void main(String[] args) {
WinAdapter audioPlayer = new WinAdapter();

audioPlayer.play("win10", "截图");
audioPlayer.play("xp", "绘图");
}
}

class Win_XP {
public void prtSc(String fileName) {
System.out.println("Name: " + fileName);
}
}

class Win_10 {
public void pic(String type, String fileName) {
System.out.println("Type: " + type + " Name: " + fileName);
}
}

interface BaseAdaoter {
public void play(String type, String fileName);
}

class WinAdapter implements BaseAdaoter {
Object os;

@Override
public void play(String type, String fileName) {
if ("win10".equals(type)) {
os = new Win_10();
((Win_10) os).pic(type, fileName);
} else {
os = new Win_XP();
((Win_XP) os).prtSc(fileName);
}
}

}


观察者模式
手工实现观察者模式
皇上有很多下人(List)
皇上要找下人
皇上发话,所有下人都要听谕
import java.util.ArrayList;
import java.util.List;

public class C观察者模式 {
public static void main(String[] args) {

皇上 h = new 皇上();
h.招下人(new 奴才());
h.招下人(new 奴才());
h.口谕();

}
}

class 皇上 {
List<下人> lst = new ArrayList<下人>();

public void 招下人(下人 x) {
lst.add(x);
}

public void 口谕() {
for (下人 x : lst) {
x.听谕();
}
}
}

interface 下人 {
void 听谕();
}

class 奴才 implements 下人 {
@Override
public void 听谕() {
System.out.println("奴才遵旨");
}
}
JAVA自带观察者实现
1. 继承Observable
2. 实现Observer
3. Observable添加Observer
4. Observable标榜setChanged(),并且notifyObservers(),缺一不可
import java.util.Observable;
import java.util.Observer;

public class C观察者模式继承版 {
public static void main(String[] args) {

皇上 h = new 皇上();
h.addObserver(new 奴才());
h.addObserver(new 奴才());
h.口谕();
}
}

class 皇上 extends Observable {

void 口谕() {
// 标记此 为已改变的对象
setChanged();
// 通知所有观察者
notifyObservers();
}
}

class 奴才 implements Observer {

@Override
public void update(Observable o, Object arg) {
System.out.println("皇上口谕");
}
}




package designpattern.bean;
public abstract class Car {
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}

public abstract void drive();
}
package designpattern.bean;
public class Benz extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}
package designpattern.bean;
public class Bmw extends Car {
public void drive() {
System.out.println(this.getName() + "----go-----------------------");
}
}

根据字符串,创建类
package designpattern;
import designpattern.bean.*;
public class C简单工厂 {
public static void main(String[] args) {
Car car = FactoryS.createCar("benz");
car.setName("benz");
car.drive();
}
}

class FactoryS {
public static Car createCar(String car) {
Car c = null;
if ("Benz".equalsIgnoreCase(car))
c = new Benz();
else if ("Bmw".equalsIgnoreCase(car))
c = new Bmw();
return c;
}
}












内部类
成员内部类
Outter.Inner inner = new Outter().new Inner();

静态内部类
访问外部类的静态成员
Outter.Inner inner = new Outter.Inner();

局部内部类
方法内部new
方法内部的变量,只能访问final的


匿名内部类
import java.util.Arrays;
import java.util.Comparator;

public class D0903数组降序 {
// 数组降序排列注意
// 1.定义降序的类, implements Comparator<Integer>
// 2.必须使用包装类,不能使用int等基本数据类型的数组
public static void main(String[] args) {
Integer red[] = { 3, 1, 6, 7, 9, 15 };
Arrays.sort(red, new ArraySortDesc());
for (int i : red) {
System.out.println(i);
}
}
}

class ArraySortDesc implements Comparator<Integer> {

@Override
public int compare(Integer o1, Integer o2) {
return (o1 < o2) ? 1 : -1;
}

}




原创粉丝点击