{
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{
@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 ListgetAll受贿记录() {
Listlst = new ArrayList();
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.把数据取出来
Listall受贿记录 = 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// 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{
@Override
public int compare(Integer o1, Integer o2) {return (o1 < o2) ? 1 : -1;
}
}