第一章 常用类
1.equals方法和=判断对象是否相等的区别
1.== 既可以比较基本类型也可以比较引用类型。对于基本类型(byte,short,int,long,float,double,char,boolean)就是比较值,对于引用类型就是比较内存地址
2.equals,如果该方法没有被重写过默认也是==;重写equals方法,会比较类中的相应属性是否都相等。(就是比较值)
2.equals方法和hashCode方法的关系
1.在哈希表中,当插入或查找一个元素时,会先根据元素的hashCode值来确定该元素在哈希表中的位置,然后再使用equals方法进行比较,如果该位置上已经有元素,则需要比较该元素和要插入或查找的元素是否相等。
3.字符串操作类String、StringBuffer、StringBuilder的区别
- String是Java中最基本的字符串类,它是一个不可变的类,即一旦创建,它的值就不能被改变了。
- StringBuffer是一个可变的字符串类,它可以在原有字符串上进行添加、删除、替换等操作,
- StringBuffer是线程安全的,
- StringBuilder是自JDK5起引入的一个可变字符串类,它是线程不安全的,但具有和StringBuffer相同的操作性能。
4.String类的常用方法如
- length():获取字符串中字符的个数,即字符串的长度。
- isEmpty():判断字符串是否为空,即长度为0。
- startsWith(String prefix):判断该字符串是否以指定前缀字符串开头。
- trim():去掉字符串两端的空格,并返回一个新的字符串。
- subString(int beginIndex):获取从指定位置开始到字符串结尾的子字符串。
- subString(int beginIndex, int endIndex):获取从指定的开始位置到结束位置之间的子字符串,注意endIndex所在的字符不包含在结果中。
- replace(oldstr, newstr):将字符串中所有的旧字符串替换成新字符串,并返回一个新的字符串。
5.包装类的自动装箱和自动拆箱、包装类常用方法
**装箱:把基本数据类型转为包装类对象**
**拆箱:把包装类对象拆为基本数据类型**
Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5;
//加法运算完成后,再次装箱,把基本数值转成对象。
**数据类型的最大最小值
Integer.MAX_VALUE和Integer.MIN_VALUE
**字符转大小写
Character.toUpperCase('x');
Character.toLowerCase('X');
**整数转进制
Integer.toBinaryString(int i) //二进制字符串
Integer.toHexString(int i)//十六进制字符串
Integer.toOctalString(int i)//八进制字符串
** 比较的方法
Integer.compare(int x, int y)
** Integer等包装类对象是“不可变”对象,即一旦修改,就是新对象,和实参就无关了
b += 10;//等价于 b = new Integer(b+10);
6.SimpleDateFormat类对日期格式化和将字符串转换成Date对象的方法
//格式化日期为字符串
public String format(Date date)
//将字符串解析成Date对象
public Date parse(String source) throws ParseException
//使用SimpleDateFormat类将Date对象格式化为字符串和将字符串解析成Date对象:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 将Date对象格式化为字符串
Date date = new Date();
String strDate = dateFormat.format(date);
System.out.println("格式化后的时间:" + strDate);
// 将字符串解析成Date对象
String str = "2023-06-09 10:07:47";
Date parsedDate = dateFormat.parse(str);
System.out.println("解析后的时间:" + parsedDate);
第二章 集合
1.Collection和Map的常用方法
Collection:
-
add(E e):向集合中添加一个元素。
-
remove(Object o):从集合中删除一个元素。
-
clear():删除集合中的所有元素。
-
size():返回集合中元素的个数。
-
isEmpty():判断集合是否为空。
-
contains(Object o):判断集合中是否包含指定元素。
-
iterator():返回一个用于遍历集合中元素的迭代器。
Map:
- put(K key, V value):将一对键值对存入Map中。
- get(Object key):根据键获取Map中对应的值。
- remove(Object key):删除Map中指定键的键值对。
- clear():删除Map中的所有键值对。
- size():返回Map中键值对的个数。
- isEmpty():判断Map是否为空。
- containsKey(Object key):判断Map中是否包含指定键。
- keySet():返回包含Map中所有键的Set集合。
2.List和Set的区别
- List是有序,可重复的,它可以保留元素的插入顺序;而Set是无序,不重复的,它不会保留元素的插入顺序。
- List可以根据下标访问元素;而Set不能通过下标访问元素,只能通过迭代器访问元素。
3.Collection和Map的区别
- Collection接口是一组对象的集合,可以用来保存一组对象;而Map接口是一组键-值对(key-value)的映射集合,每个键对应一个值
- Collection接口中可以保存重复的元素,但是Map接口中的键是唯一的,不允许重复。
- Collection接口中的元素是通过迭代器进行访问的,而Map接口中的元素可以通过键来进行访问。
4.ArrayList和LinkedList的区别
-
ArrayList内部用数组实现的,而LinkedList内部是用双向链表实现的。
-
ArrayList底层采用数组实现,支持快速随机访问,例如get和set操作是常数时间的(O(1)),但它的插入和删除操作是线性时间的(O(n))。
-
LinkedList底层采用双向链表实现,因此它的插入和删除操作是常数时间的(O(1)),但它的随机访问性能相对较差,例如get和set操作需要遍历链表(O(n))。
5.Iterator遍历集合
@Test
public void test02(){
Collection coll = new ArrayList();
coll.add("小李广");
coll.add("扫地僧");
coll.add("石破天");
Iterator iterator = coll.iterator();//获取迭代器对象
while(iterator.hasNext()) {//判断是否还有元素可迭代
System.out.println(iterator.next());//取出下一个元素
}
}
6.HashMap的遍历
for (Object obj : hashMap.keySet()) {
System.out.println(obj + "=" + hashMap.get(obj));
}
7.TreeSet实现自然排序和定制排序
//自然排序,针对string的
@Test
public void test1(){
TreeSet set = new TreeSet();
set.add("MM");
set.add("CC");
set.add("AA");
set.add("DD");
set.add("ZZ");
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
/**定制排序
* */
@Test
public void test3(){
//按照User的姓名的从小到大的顺序排列
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof User && o2 instanceof User){
User u1 = (User)o1;
User u2 = (User)o2;
return u1.name.compareTo(u2.name);
}
throw new RuntimeException("输入的类型不匹配");
}
};
TreeSet set = new TreeSet(comparator);
set.add(new User("Tom",12));
set.add(new User("Rose",23));
set.add(new User("Jerry",2));
set.add(new User("Eric",18));
set.add(new User("Tommy",44));
set.add(new User("Jim",23));
set.add(new User("Maria",18));
//set.add(new User("Maria",28));
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
/*
举例:按照age从小到大的顺序排列,如果age相同,则按照name从大到小的顺序排列
* */
public int compareTo(Object o) {
if(this == o){
return 0;
}
if(o instanceof User){
User user = (User)o;
int value = this.age - user.age;
if(value != 0){
return value;
}
return -this.name.compareTo(user.name);
}
throw new RuntimeException("输入的类型不匹配");
}
}
8.Collections和Arrays工具类的常用方法
.Collections
- sort(List list):对列表进行排序。
- reverse(List list):将列表中的元素翻转。
- binarySearch(List<?> list, T key):使用二分搜索算法查找指定元素在列表中的索引。
- fill(List<? super T> list, T obj):使用指定的对象填充列表中的所有元素。
- max(Collection<? extends T> coll):返回指定集合中的最大元素。
- min(Collection<? extends T> coll):返回指定集合中的最小元素。
- frequency(Collection<?> c, Object o):返回指定集合中指定元素出现的次数。
- shuffle(List<?> list):随机打乱列表中的元素顺序。
- disjoint(Collection<?> c1, Collection<?> c2):判断两个集合是否有交集。
Arrays
- sort(T[] a):对数组进行排序。
- binarySearch(T[] a, T key):使用二分搜索算法查找指定元素在数组中的索引。
- equals(T[] a, T[] a2):判断两个数组是否相等。
- fill(T[] a, T val):使用指定的值填充数组中的所有元素。
- copyOf(T[] original, int newLength):将一个数组复制到一个新数组,新数组长度为newLength,超出部分会被填充默认值。
- toString(T[] a):返回一个包含数组中所有元素的字符串表示形式。
9.泛型类、泛型接口、泛型方法的语法,使用方法
//泛型类
public class MyClass<T> {
private T value;
public MyClass(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
MyClass<String> myClass1 = new MyClass<>("Hello");
MyClass<Integer> myClass2 = new MyClass<>(123);
String str = myClass1.getValue();
int num = myClass2.getValue();
//泛型接口
public interface MyInterface<T> {
T getValue();
}
public class MyClass implements MyInterface<String> {
@Override
public String getValue() {
return "Hello";
}
}
//泛型方法
public class MyUtils {
public static <T> void print(T[] arr) {
for (T item : arr) {
System.out.println(item);
}
}
}
String[] arr1 = {"Hello", "World"};
Integer[] arr2 = {1, 2, 3};
MyUtils.print(arr1); // 自动推断为 T 为 String 类型
MyUtils.print(arr2); // 自动推断为 T 为 Integer 类型
10.使用泛形的好处
- 类型安全:Java泛型可以让编译器在编译时检查类型,从而避免了类型转换错误和类型不匹配的运行时异常
- 代码重用:使用泛型可以创建可重用的代码,可以在不同类型上运行。
- 性能优化:使用泛型可以避免对基本类型进行装箱和拆箱操作,从而提高程序的执行效率
第三章 多线程
1.线程的三种创建方式及其区别
方式一:继承Thread类
方式二:实现Runnable接口
方式三:实现Callable接口
区别:
-
继承Thread:线程代码存放Thread子类run方法中。
-
实现Runnable:线程代码存在接口的子类的run方法。
-
实现Callable接口:线程需要执行的操作声明在call()中
2.线程的状态及状态转换
NEW(新建)
:线程刚被创建,但是并未启动。还没调用start方法。
RUNNABLE(可运行)
:这里没有区分就绪和运行状态。
Teminated(被终止)
:表明此线程已经结束生命周期,终止运行。
TIMED_WAITING(计时等待)
WAITING(无限等待)
3.线程调度之线程优先级、线程休眠、线程让步、线程插队等
Thread类的三个优先级常量:
- MAX_PRIORITY(10):最高优先级
- MIN _PRIORITY (1):最低优先级
- NORM_PRIORITY (5):普通优先级,默认情况下main线程具有普通优先级。
-
public final int getPriority() :返回线程优先级
-
public final void setPriority(int newPriority) :改变线程的优先级,范围在[1,10]之间。
线程休眠
sleep():使当前线程休眠指定的毫秒数
线程让步
yield():让当前线程释放CPU资源,以便让其他线程使用
线程插队
join():方法会阻塞当前线程,直到被等待的线程执行完毕。
4.线程同步之synchronized和ReentrantLock实现线程同步
synchronized
同步代码块
synchronized(同步锁){
需要同步操作的代码
}
同步方法
public synchronized void method(){
可能会产生线程安全问题的代码
}
ReentrantLock
class A{
//1. 创建Lock的实例,必须确保多个线程共享同一个Lock实例
private final ReentrantLock lock = new ReenTrantLock();
public void m(){
//2. 调动lock(),实现需共享的代码的锁定
lock.lock();
try{
//保证线程安全的代码;
}
finally{
//3. 调用unlock(),释放共享代码的锁定
lock.unlock();
}
}
}
5.线程死锁的解决方式及其实现
- 采用统一的获取资源的顺序
- 检测和恢复死锁:
- 使用超时等待机制
第四章 IO流
1.File类的常用方法
-
exists()方法:判断文件或目录是否存在,返回布尔类型的值true或false。
-
isFile()方法:判断是否是一个文件,如果是返回true,否则返回false。
-
isDirectory()方法:判断是否是一个目录,如果是返回true,否则返回false。
-
length()方法:获取文件的大小,返回一个long类型的值表示文件的字节数。
-
listFiles()方法:获取目录下的所有文件和子目录,返回一个File数组,数组中的每个元素是目录下的一个文件或目录。如果该File对象不是一个目录,则返回null。
2.递归删除目录文件
public static void deleteDir(File dir) {
if (dir.isDirectory()) {
File[] children = dir.listFiles();
for (File child : children) {
deleteDir(child);
}
}
boolean success = dir.delete();
if (success) {
System.out.println("已经成功删除:" + dir.getAbsolutePath());
} else {
System.out.println("删除失败:" + dir.getAbsolutePath());
}
}
public static void main(String[] args) {
File directory = new File("C:/temp");
deleteDir(directory);
}
3.流的分类
-
按数据的流向不同分为:输入流和输出流。
- 输入流 :把数据从
其他设备
上读取到内存
中的流。- 以InputStream、Reader结尾
- 输出流 :把数据从
内存
中写出到其他设备
上的流。- 以OutputStream、Writer结尾
- 输入流 :把数据从
-
按操作数据单位的不同分为:字节流(8bit)和字符流(16bit)。
- 字节流 :以字节为单位,读写数据的流。
- 以InputStream、OutputStream结尾
- 字符流 :以字符为单位,读写数据的流。
- 以Reader、Writer结尾
- 字节流 :以字节为单位,读写数据的流。
-
根据IO流的角色不同分为:节点流和处理流。
节点流:直接从数据源或目的地读写数据
处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
4.字符流和字节流的区别
- 字节流按字节读取和写入数据。它们可以用于读取和写入任何类型的数据,包括二进制数据和文本数据。
- 字符流按字符或字符串读取和写入数据。它们只能用于读取和写入文本数据
- 字符流内部使用了缓冲区,因此在输入和输出时效率较高
- 字符流能够自动处理 Unicode 编码的字符。字节流只能处理 ASCII 编码的字符。
5.常用字符流和常用字节流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GM1RGEyU-1686746832995)(C:\Users\李\AppData\Roaming\Typora\typora-user-images\image-20230612143624328.png)]
6.利用字符流或字节流复制文件夹级文件
看实验
7.字节缓冲流的创建及用法
- 创建字节缓冲输入流(输出同理)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("file.txt"));
2.读取数据
byte[] buffer = new byte[1024];
int bytesRead = bis.read(buffer);
3.写入数据
byte[] buffer = "Hello World!".getBytes();
bos.write(buffer);
4.关闭
bis.close();
bos.close();
8.转换流的创建及用法
public class ConvertStreamDemo {
public static void main(String[] args) throws IOException {
// 创建 InputStreamReader 对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("input.txt"), "UTF-8");
// 创建 OutputStreamWriter 对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("output.txt"), "UTF-8");
// 读取数据并写入到输出流中
int c = isr.read();
while (c != -1) {
osw.write(c);
c = isr.read();
}
// 关闭流
isr.close();
osw.close();
}
9.对象序列化
第五章 注解
1.Java常用注解
- @Override:标记方法重写父类的方法
- @Deprecated:标记该方法已经过时,不推荐使用。
2.元注解有哪些,各自的作用
- @Target:用于指定注解的应用范围,可以用于类、方法、参数等
- @Retention:用于指定注解的生命周期,可以在编译期、运行期或者是类加载期存在。
- @Documented:用于指定被注解的类、方法、字段等是否包含在文档中。
- @Inherited:用于指定被注解的类是否可以被继承,如果一个类使用了被@Inherited注解的注解,则其子类也会自动继承该注解。
- @Repeatable:用于指定注解是否可以重复。
第六章 网络编程
1.TCP/IP网络协议模型
- 数据链路层
- 网络层
- 传输层
- 应用层
2.URL编程
URL的基本结构由5部分组成:
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
URL url = new URL("http://localhost:8080/examples/myTest.txt");
System.out.println("getProtocol() :"+url.getProtocol());//获取该URL的协议名
System.out.println("getHost() :"+url.getHost());//获取该URL的主机名
System.out.println("getPort() :"+url.getPort());//获取该URL的端口号
System.out.println("getPath() :"+url.getPath());//获取该URL的文件路径
System.out.println("getFile() :"+url.getFile());//获取该URL的文件路径
System.out.println("getQuery() :"+url.getQuery());//获取该URL的查询名
3.TCP和UDP协议的区别及各自的适用场景
区别:
- 1.TCP是面向连接的,UDP是面向无连接
无连接:发送数据之前不需要建立连接 - 2.TCP是可靠传输,UDP是不可靠
不可靠:收到报文后不需要给出任何确认 - 3.TCP只支持点对点通信,UDP支持一对一,一对多,多对一,多对多。
- 4.TCP是面向字节流的,UDP是面向报文的
字节流:以字节为单位,可以分成若干组发送,报文:只能一次发完。 - 5.TCP有拥塞控制机制,UDP没有
- 6.TCP首部开销(20字节)比UDP首部开销(8字节)大
- 7.UDP的主机不需要维持复杂的连接状态表
TCP适应场景:文件传输、网页浏览、邮件发送
UDP适应场景:音频、视频和普通数据的传输。例如视频会议
4.TCP通信和UDP通信编程
TCP
//服务器
package com.atguigu.tcp.one;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args)throws Exception {
//1、准备一个ServerSocket对象,并绑定8888端口
ServerSocket server = new ServerSocket(8888);
System.out.println("等待连接....");
//2、在8888端口监听客户端的连接,该方法是个阻塞的方法,如果没有客户端连接,将一直等待
Socket socket = server.accept();
InetAddress inetAddress = socket.getInetAddress();
System.out.println(inetAddress.getHostAddress() + "客户端连接成功!!");
//3、获取输入流,用来接收该客户端发送给服务器的数据
InputStream input = socket.getInputStream();
//接收数据
byte[] data = new byte[1024];
StringBuilder s = new StringBuilder();
int len;
while ((len = input.read(data)) != -1) {
s.append(new String(data, 0, len));
}
System.out.println(inetAddress.getHostAddress() + "客户端发送的消息是:" + s);
//4、获取输出流,用来发送数据给该客户端
OutputStream out = socket.getOutputStream();
//发送数据
out.write("欢迎登录".getBytes());
out.flush();
//5、关闭socket,不再与该客户端通信
//socket关闭,意味着InputStream和OutputStream也关闭了
socket.close();
//6、如果不再接收任何客户端通信,可以关闭ServerSocket
server.close();
}
}
//客户端
package com.atguigu.tcp.one;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
// 1、准备Socket,连接服务器,需要指定服务器的IP地址和端口号
Socket socket = new Socket("127.0.0.1", 8888);
// 2、获取输出流,用来发送数据给服务器
OutputStream out = socket.getOutputStream();
// 发送数据
out.write("lalala".getBytes());
//会在流末尾写入一个“流的末尾”标记,对方才能读到-1,否则对方的读取方法会一致阻塞
socket.shutdownOutput();
//3、获取输入流,用来接收服务器发送给该客户端的数据
InputStream input = socket.getInputStream();
// 接收数据
byte[] data = new byte[1024];
StringBuilder s = new StringBuilder();
int len;
while ((len = input.read(data)) != -1) {
s.append(new String(data, 0, len));
}
System.out.println("服务器返回的消息是:" + s);
//4、关闭socket,不再与服务器通信,即断开与服务器的连接
//socket关闭,意味着InputStream和OutputStream也关闭了
socket.close();
}
}
UDP
//发送端
package com.atguigu.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
public class Send {
public static void main(String[] args)throws Exception {
// 1、建立发送端的DatagramSocket
DatagramSocket ds = new DatagramSocket();
//要发送的数据
ArrayList<String> all = new ArrayList<String>();
all.add("尚硅谷让天下没有难学的技术!");
all.add("学高端前沿的IT技术来尚硅谷!");
all.add("尚硅谷让你的梦想变得更具体!");
all.add("尚硅谷让你的努力更有价值!");
//接收方的IP地址
InetAddress ip = InetAddress.getByName("127.0.0.1");
//接收方的监听端口号
int port = 9999;
//发送多个数据报
for (int i = 0; i < all.size(); i++) {
// 2、建立数据包DatagramPacket
byte[] data = all.get(i).getBytes();
DatagramPacket dp = new DatagramPacket(data, 0, data.length, ip, port);
// 3、调用Socket的发送方法
ds.send(dp);
}
// 4、关闭Socket
ds.close();
}
}
//接收端
package com.atguigu.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Receive {
public static void main(String[] args) throws Exception {
// 1、建立接收端的DatagramSocket,需要指定本端的监听端口号
DatagramSocket ds = new DatagramSocket(9999);
//一直监听数据
while(true){
//2、建立数据包DatagramPacket
byte[] buffer = new byte[1024*64];
DatagramPacket dp = new DatagramPacket(buffer,buffer.length);
//3、调用Socket的接收方法
ds.receive(dp);
//4、拆封数据
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str);
}
// ds.close();
}
}
第七章 JDBC
1.数据库驱动注册
Class.forName("com.mysql.cj.jdbc.Driver" );
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase", "username", "password");
2.DriverManager类主要方法
- registerDriver(Driver driver): 注册一个数据库驱动程序。
- getDriver(String url): 通过指定JDBC URL获取对应的数据库驱动程序。
- getConnection(String url, String user, String password): 建立一个数据库连接。
- setLoginTimeout(int seconds): 设置JDBC驱动程序的登录超时时间(以秒为单位)。
- setLogWriter(PrintWriter out): 设置JDBC驱动程序的日志输出流。
3.Connection类常用方法
- createStatement():创建一个Statement对象以便执行SQL语句。
- prepareStatement(String sql):创建一个预编译的PreparedStatement对象以便执行SQL语句。
- setAutoCommit(boolean autoCommit):设置是否自动提交事务。
- commit():提交当前处于事务状态的操作。
- rollback():回滚当前处于事务状态的操作。
- close():关闭Connection对象。
4.Statement和PreparedStatement的区别
1.PreparedStatement在使用时只需要编译一次,就可以运行多次,Statement每运行一次就编译一次,所以PreparedStatement的效率更高
2.PreparedStatement需要的sql语句为用?(占位符)来替换值,Statement所需要的sql语句为字符串拼接
3.PreparedStatement解决了sql注入的问题,Statement没有解决,
5.使用PreparedStatement执行增删改查操作
//通用的增、删、改操作(体现一:增、删、改 ; 体现二:针对于不同的表)
public void update(String sql,Object ... args){
Connection conn = null;
PreparedStatement ps = null;
try {
//1.获取数据库的连接
conn = JDBCUtils.getConnection();//JDBCUtils是自己写的
//2.获取PreparedStatement的实例 (或:预编译sql语句)
ps = conn.prepareStatement(sql);
//3.填充占位符
for(int i = 0;i < args.length;i++){
ps.setObject(i + 1, args[i]);
}
//4.执行sql语句
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.关闭资源
JDBCUtils.closeResource(conn, ps);
}
}
6.ResultSet操作查询结果集
// 通用的针对于不同表的查询:返回一个对象 (version 1.0)
public <T> T getInstance(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1.获取数据库连接
conn = JDBCUtils.getConnection();
// 2.预编译sql语句,得到PreparedStatement对象
ps = conn.prepareStatement(sql);
// 3.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// 4.执行executeQuery(),得到结果集:ResultSet
rs = ps.executeQuery();
// 5.得到结果集的元数据:ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
T t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {// 遍历每一个列
// 获取列值
Object columnVal = rs.getObject(i + 1);
// 获取列的别名:列的别名,使用类的属性名充当
String columnLabel = rsmd.getColumnLabel(i + 1);
// 6.2使用反射,给对象的相应属性赋值
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnVal);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 7.关闭资源
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
7.JDBC编程步骤
- 加载数据库驱动
- 建立数据库连接
- 执行SQL语句
- 处理查询结果集
- 提交事务或回滚事务
- 释放资源
第八章 反射
1.反射的作用
1.动态加载类
public class ReflectionTest {
//体会反射的动态性:动态的创建指定字符串对应类的对象,并调用指定的方法
public Object invoke(String className,String methodName) throws Exception {
Class clazz = Class.forName(className);
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
//动态的创建指定字符串对应类的对象
Object obj = constructor.newInstance();
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
return method.invoke(obj);
}
@Test
public void test2() throws Exception {
String info = (String) invoke("com.atguigu.java1.Person", "show");
System.out.println("返回值为:" + info);
}
}
2.获取类的构造函数
3.动态创建对象
4.调用私有方法
5.广泛应用于框架
2.获取Class类对象的三种方式
通过类的class属性获取
Class clazz = String.class;
调用该实例的getClass()方法获取Class对象
Class clazz = "www.atguigu.com".getClass();
通过Class类的静态方法forName()获取
Class clazz = Class.forName("java.lang.String");
3.Class类的常用方法
获取类的构造方法列表
Constructor<?>[] constructors = clazz.getConstructors(); // 获取所有公共构造方法列表
Constructor<?>[] constructors = clazz.getDeclaredConstructors(); // 获取所有构造方法列表(包括私有构造方法)
Constructor<?> constructor = clazz.getConstructor(Class<?>... parameterTypes); // 获取指定参数列表的公共构造方法
Constructor<?> constructor = clazz.getDeclaredConstructor(Class<?>... parameterTypes); // 获取指定参数列表的构造方法(包括私有构造方法)
获取类的接口列表
Class<?>[] interfaces = clazz.getInterfaces(); // 获取当前类的接口列表
Class<?> superclass = clazz.getSuperclass(); 获取当前类的父类
获取类的属性列表:
Field[] fields = clazz.getFields(); // 获取所有公共属性列表(包括父类的公共属性)
Field[] fields = clazz.getDeclaredFields(); // 获取所有属性列表(包括私有属性)
Field field = clazz.getField(String name); // 获取指定名称的公共属性
Field field = clazz.getDeclaredField(String name); // 获取指定名称的属性(包括私有属性)
获取类的方法列表:
Method[] methods = clazz.getMethods(); // 获取所有公共方法列表(包括父类的公共方法)
Method[] methods = clazz.getDeclaredMethods(); // 获取所有方法列表(包括私有方法)
Method method = clazz.getMethod(String name, Class<?>... parameterTypes); // 获取指定名称和参数列表的公共方法
Method method = clazz.getDeclaredMethod(String name, Class<?>... parameterTypes); // 获取指定名称和参数列表的方法(包括私有方法)
4.反射机制操作获取和设置属性值
public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person("Tom", 18);
// 获取属性名称、类型和修饰符等信息
Field nameField = person.getClass().getDeclaredField("name");
String name = nameField.getName();
Class<?> type = nameField.getType();
int modifiers = nameField.getModifiers();
// 获取属性值
Object value = nameField.get(person);
System.out.println(name + " = " + value);
// 设置属性值
nameField.set(person, "Jerry");
value = nameField.get(person);
System.out.println(name + " = " + value);
}
5.通过反射机制获取属性的getter/setter方法操作属性
public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person("Tom", 18);
// 获取setter方法
Method setNameMethod = person.getClass().getMethod("setName", String.class);
// 设置属性值
setNameMethod.invoke(person, "Jerry");
// 获取getter方法
Method getNameMethod = person.getClass().getMethod("getName");
// 获取属性值
Object name = getNameMethod.invoke(person);
System.out.println(name);
}
第九章 Swing
1.JFrame类
顶级容器类之一,它提供了一个框架来在屏幕上创建、调整和显示GUI应用程序窗口。
- setTitle():设置窗口的标题。
- setSize():设置窗口的大小。
- setLayout():设置容器的布局管理器。
- setDefaultCloseOperation():设置窗口关闭时的操作。
- setVisible():显示或隐藏窗口。
2.常用布局管理器及其布局方式
- BorderLayout:将容器划分为五个区域:北、南、东、西和中心,每个区域放置一个组件。
- FlowLayout:按照添加的组件顺序依次摆放,如果超出容器范围则自动换行,类似于文字排版。
- GridLayout:将容器划分为若干行、若干列的网格,并按照顺序依次向网格中添加组件。
- CardLayout:将容器中的每个组件视为一张卡片,只显示当前卡片,可以通过切换卡片来显示不同的组件内容。
- BoxLayout:按照水平或垂直方向将组件依次排列。
3.Swing事件处理流程
事件源注册监听器
监听器实现:
事件分派
事件处理
事件反馈
4.Swing常用事件处理
- ActionEvent:当组件(例如按钮或菜单项)被用户点击时触发。
- MouseEvent:当鼠标与组件交互时触发事件。
- FocusEvent:当组件获得或失去焦点时触发事件。
- WindowEvent:当窗口(例如JFrame或JDialog)的状态发生变化时(例如打开或关闭)触发事件。
- KeyEvent:该事件与键盘交互有关,例如键盘按下、松开或敲击等。
- MouseWheelEvent:该事件与鼠标滚轮有关。
- ListSelectionEvent:该事件在用户选择决定性更改时触发,要么将某项选中,要么取消某项选中。
5.中间容器组件JScrollPane、JPanel的用法
- JScrollPane组件一般用于容纳视图或容器,并提供一个可滚动的视窗。
- JPanel是一个空白容器,可以用来组织其他组件,它常作为其他布局管理器的容器。
6.Swing常用组件用法
JLabel是一个用于显示文本或图像的组件。
JTextField是一个文本输入框组件,用户可以在其中输入文本。
JButton是一个按钮组件,用户可以单击它执行某些操作。
JCheckBox是一个复选框组件,用户可以选中或取消选中它,常用于表示二进制选项。
ame类
顶级容器类之一,它提供了一个框架来在屏幕上创建、调整和显示GUI应用程序窗口。
- setTitle():设置窗口的标题。
- setSize():设置窗口的大小。
- setLayout():设置容器的布局管理器。
- setDefaultCloseOperation():设置窗口关闭时的操作。
- setVisible():显示或隐藏窗口。
2.常用布局管理器及其布局方式
- BorderLayout:将容器划分为五个区域:北、南、东、西和中心,每个区域放置一个组件。
- FlowLayout:按照添加的组件顺序依次摆放,如果超出容器范围则自动换行,类似于文字排版。
- GridLayout:将容器划分为若干行、若干列的网格,并按照顺序依次向网格中添加组件。
- CardLayout:将容器中的每个组件视为一张卡片,只显示当前卡片,可以通过切换卡片来显示不同的组件内容。
- BoxLayout:按照水平或垂直方向将组件依次排列。
3.Swing事件处理流程
事件源注册监听器
监听器实现:
事件分派
事件处理
事件反馈
4.Swing常用事件处理
- ActionEvent:当组件(例如按钮或菜单项)被用户点击时触发。
- MouseEvent:当鼠标与组件交互时触发事件。
- FocusEvent:当组件获得或失去焦点时触发事件。
- WindowEvent:当窗口(例如JFrame或JDialog)的状态发生变化时(例如打开或关闭)触发事件。
- KeyEvent:该事件与键盘交互有关,例如键盘按下、松开或敲击等。
- MouseWheelEvent:该事件与鼠标滚轮有关。
- ListSelectionEvent:该事件在用户选择决定性更改时触发,要么将某项选中,要么取消某项选中。
5.中间容器组件JScrollPane、JPanel的用法
- JScrollPane组件一般用于容纳视图或容器,并提供一个可滚动的视窗。
- JPanel是一个空白容器,可以用来组织其他组件,它常作为其他布局管理器的容器。
6.Swing常用组件用法
JLabel是一个用于显示文本或图像的组件。
JTextField是一个文本输入框组件,用户可以在其中输入文本。
JButton是一个按钮组件,用户可以单击它执行某些操作。
JCheckBox是一个复选框组件,用户可以选中或取消选中它,常用于表示二进制选项。
JRadioButton是一个单选按钮组件,用户可以从一组选择项中选中一个,常用于组织选项。
LXY