Java(二十一)
程序员文章站
2022-07-07 21:30:08
...
知识点一:作业回顾
题目一:给定一个字符串, 统计每个字符出现的次数
方法一:将字符作为数组下标,对字符串进行遍历。
@Test
public void test2() {
String string = "ajfalkjsdflkajsdflasjdf348729384723984汉不苛是要困右百百呆在中2342lalakjfds";
int[] arr = new int[65536];
for (int i = 0; i < string.length(); i++) {
char ch = string.charAt(i);
arr[ch]++;
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] > 0) {
System.out.println((char)i + ":" + arr[i]);
}
}
}
方法二:利用get获取值对象,把字符作为键对象传入到hashMap中
@Test
public void test1() {
String string = "ajfalkjsdflkajsdflasjdf348729384723984汉不苛是要困右百百呆在中2342lalakjfds";
// 'a' : 5, 's' : 8
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < string.length(); i++) {
char ch = string.charAt(i);
Integer count = map.get(ch);
if (count == null) {
count = 0;
}
map.put(ch, ++count);
}
System.out.println(map);
}
题目二:复制某目录下文件
一:复制文件的方法写出来
public void copyFile(File file1, File file2) {
System.out.println("复制文件:" + file1 + " 到 " + file2);
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
byte[] buf = new byte[8192];
int count;
while ((count = fis.read(buf)) != -1) {
fos.write(buf, 0, count);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
二:复制目录的方法写出来
public void copyDir(File file1, File file2) {
file2.mkdirs(); // 先把目标目录创建出来.
File[] files = file1.listFiles();
if (files == null) {
System.out.println(file1 + " 不允许访问!!");
return;
}
for (int i = 0; i < files.length; i++) {
File target = new File(file2.getAbsolutePath() + "\\" + files[i].getName());
if (files[i].isFile()) {
// 直接复制文件
copyFile(files[i], target);
} else {
// 如果是目录, 直接让子目录递归到目标的子目录中
copyDir(files[i], target);
}
}
}
三:实现
//把C:/Program Files 复制为 D:/a/Program Files
@Test
public void test3() {
File tmp = new File("D:/a");
tmp.mkdir();
File file1 = new File("C:/Program Files");
File file2 = new File(tmp, file1.getName());
copyDir(file1, file2);
}
知识点二:线程通信
线程通信这里我们使用的还是Account这个例子
使用wait和notify方法
(1)java Bean
public class Account {
private String name;
private int balance;
public Account() {}
public Account(String name, int balance) {
this.name = name;
this.balance = balance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account{" +
"name='" + name + '\'' +
", balance=" + balance +
'}';
}
}
(2)存钱
public class Deposit implements Runnable {
private Account account;
public Deposit(Account account) {
this.account = account;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
synchronized ("") {
int balance = account.getBalance();
account.setBalance(balance + 1000);
System.out.println(Thread.currentThread().getName() + " 存完钱 : " + account);
"".notify();
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(3)取钱
public Withdraw(Account account) {
this.account = account;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
synchronized ("") {
if (account.getBalance() < 1000) {
System.out.println("钱不够, 进入等待");
try {
"".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
account.setBalance(account.getBalance() - 1000);
System.out.println(Thread.currentThread().getName() + " 取完钱后 : " + account);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
(4)实现
public class AccountTest {
public static void main(String[] args) {
Account a = new Account("张三", 0);
Runnable runner2 = new Withdraw(a);
Thread thread2 = new Thread(runner2);
thread2.setName("取钱柜台1");
thread2.start();
Runnable runner1 = new Deposit(a);
Thread thread1 = new Thread(runner1);
thread1.setName("存钱柜台1");
thread1.start();
}
}
知识点三:wait和notify的用法
public class PrintRunner implements Runnable {
private int i = 1;
@Override
public void run() {
for (int j = 0; j < 50; j++) {
synchronized ("") {
"".notify();
System.out.println(Thread.currentThread().getName() + " : " + i++);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (j < 49) {
try {
"".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class PrintRunnerTest {
public static void main(String[] args) {
PrintRunner printRunner = new PrintRunner();
Thread thread1 = new Thread(printRunner);
Thread thread2 = new Thread(printRunner);
thread1.setName("线程1");
thread2.setName("线程2");
thread1.start();
thread2.start();
}
}
知识点四:反射
一、理解
反射:用另一种创建对象,使用对象
反射的好处:把原来的编译错误延迟成运行时异常。
Class clazz = Class.forName(全限定类名);//包名.子包名.子子子包名
Class时Java程序中的数据类型的描述
class Teacher extends HashMap implements Comparable, Serializable, Runnable {
public static String school;
public static void staticTest() {
System.out.println("staticTest()...");
}
private String name;
private int age;
private String gender;
public Teacher() {}
public Teacher(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
private int lesson(String content, String room, int hours) {
System.out.println("老师在[" + room + "]教室上[" + content + "]课, 共上了[" + hours + "]小时");
//throw new RuntimeException("无端端的异常");
return 10;
}
@Override
public int compareTo(Object o) {
return 0;
}
@Override
public void run() {
}
}
测试及使用
①正常使用
@Test
public void test1() {
// 创建对象
/*
Teacher t1 = new Teacher(); // 硬编码, 在编译时强烈的依赖类.
t1.name = "宋红康";
t1.age = 30;
t1.gender = "男";
System.out.println(t1.name);
System.out.println(t1.age);
System.out.println(t1.gender);
System.out.println(t1);
*/
Teacher t2 = new Teacher("佳佳", 20, "女");
System.out.println(t2);
}
②反射使用:根据类模板直接创建实体对象
@Test
public void test2() {
try {
// 类模板对象. 软编码, 在编译时不是强烈的依赖类.
Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");// 手工加载类模板
Object object = clazz.newInstance(); // 根据类模板直接创建实体对象, 无参构造器
System.out.println(object);
} catch (ClassNotFoundException e) { // 在运行时没有找到类, 或类名错误.
e.printStackTrace();
} catch (IllegalAccessException e) { // 对于访问的成员没有访问权限时, 出这个问题
e.printStackTrace();
} catch (InstantiationException e) { // 实例化异常, 在创建对象时出问题.
e.printStackTrace();
}
}
③使用反射对非私有化 的属性进行赋值
@Test
public void test3() {
try {
Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
Object object = clazz.newInstance();
// object.name = "宋宋"
// 1) 向类模板对象要属性定义对象
// 属性定义 : 修饰符, 数据类型, 属性名.
Field nameField = clazz.getField("name"); // 提供属性名称 获取相应的属性定义对象
// 2) 给属性赋值, 必须再定位目标this对象.
nameField.set(object, "宋宋"); // object.name = "宋宋";
Object name = nameField.get(object);
System.out.println(name); // System.out.println(object.name);
// 修改age属性
Field ageField = clazz.getField("age");
ageField.set(object, 30); // object.age = 30
System.out.println(ageField.get(object));
Field genderField = clazz.getField("gender");
genderField.set(object, "男");
System.out.println(genderField.get(object));
System.out.println(object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
④使用反射对私有化的属性进行赋值
@Test
public void test4() {
try {
Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
Object object = clazz.newInstance();
//Field nameField = clazz.getField("name"); // getField方法只能获取到本类中的公共属性,还包括从父类继承的公共属性
Field nameField = clazz.getDeclaredField("name"); // 获取本类中声明的所有属性, 包括私有的.
System.out.println(nameField);
nameField.setAccessible(true); // 设置为可访问. 暴力反射.
nameField.set(object, "宋宋");
Object name = nameField.get(object);
System.out.println(name);
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true); // 突破封装性
ageField.set(object, 30);
Field genderField = clazz.getDeclaredField("gender");
genderField.setAccessible(true);
genderField.set(object, "男");
System.out.println(object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) { // 对于访问的成员没有访问权限
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) { // 没有这个属性
e.printStackTrace();
}
}
⑤获取类模板的途径有4种
@Test
public void test5() throws Exception {
// 获取类模板对象的途径 有4种
// 1) 已知类, 通过类的静态属性.class来获取,最为安全可靠,程序性能最高
Class clazz1 = Teacher.class; // 使用最多
// 2) 已经拥有了对象, 然后通过对象进一步获取它对应的类模板
Teacher teacher = new Teacher("佟刚", 40, "男");
Class clazz2 = teacher.getClass();
System.out.println(clazz1 == clazz2);
// 3) 作为反射的第一条语句
Class clazz3 = Class.forName("com.atguigu.javase.reflect.Teacher");
//System.out.println(clazz3);
System.out.println(clazz1 == clazz3);
// 4) 先获取一个类加载器对象, 再通过类加载器对象的loadClass方法
// 下面的代码是固定的写法,用于获取当前类的类载器
//ClassLoader classLoader = this.getClass().getClassLoader();// 每个类模板一定知道是哪个类加载器加载的它
ClassLoader classLoader = ReflectTest.class.getClassLoader();// 每个类模板一定知道是哪个类加载器加载的它
Class clazz4 = classLoader.loadClass("com.atguigu.javase.reflect.Teacher");
System.out.println(clazz3 == clazz4);
Class<? extends Serializable> aClass = new Serializable() {}.getClass();
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (int i = 0; i < declaredConstructors.length; i++) {
System.out.println(declaredConstructors[i]);
}
Constructor<? extends Serializable> declaredConstructor = aClass.getDeclaredConstructor(ReflectTest.class);
declaredConstructor.setAccessible(true);
Serializable serializable = declaredConstructor.newInstance(this);
System.out.println(serializable);
}
二、双亲委派机制
// 双亲委派机制 // 1) 首先由系统类加载器发起类加载请求. // 2) 把加载任务委托给父类加载器:扩展类加载器 // 3) 扩展类加载器委托给引导类加载器, 此时引导类加载器要判断, 如果不是核心类, 驳回请求 // 4) 扩展类加载器进一步也要判断, 是我该由加载, 如果也不该我加载, 驳回请求 // 5) 系统类加载器发现全部被驳回后, 自己直接加载了. // 1) 首先由系统类加载器发起类加载请求. // 2) 把加载任务委托给父类加载器:扩展类加载器 // 3) 扩展类加载器委托给引导类加载器, 此时引导类加载器要判断, 是核心类, 当仁不让, 立刻加载 // 4) 扩展类加载器发现已经加载过了, 不加载并返回 // 5) 系统类加载器发现已经加载过了, 不加载并返回.
@Test
public void test8() {
// 系统类加载器是最常用, 主要用于加载我们自定义类
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
// 扩展类加载器, 负责加载jre/lib/ext目录下的所有jar
ClassLoader extClassLoader = systemClassLoader.getParent();
System.out.println(extClassLoader);
// 引导类加载器, 是最底层最核心的类加载器, 负责加载jre/lib目录下的所有.jar.
ClassLoader boostrapClassLoader = extClassLoader.getParent();
System.out.println(boostrapClassLoader);
}
①类的加载可以加载各种资源。只要是项目所包含的.jar文件或src目录下 的所有资源,它可以加载classpath路径中的任意文件
@Test
public void test9() throws IOException {
// 类加载可以 加载各种资源, 只要是项目所包含的.jar文件或src目录下的所有资源.
// 它可以加载classpath路径中的任意文件
//InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/sun/corba/se/impl/logging/LogStrings.properties");
InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/atguigu/javase/hello.properties");
Properties properties = new Properties();
properties.load(is);
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//"javax/sql/rowset/rowset.properties"
}
②构造器的反射应用
@Test
public void test10() {
Class clazz = null;
try {
clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
//Object object = clazz.newInstance();
//public Teacher(String name, int age, String gender) {
// 找到指定的构造器, 参数中提供构造方法的形参类型列表
Constructor constructor = clazz.getConstructor(String.class, int.class, String.class);
// newInstance()调用时必须传递和形参一致的实参列表
Object object = constructor.newInstance("宋宋", 30, "男"); // 相当于new Teacher("宋宋", 30, "男");
System.out.println(object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
⑤方法的反射应用
@Test
public void test11() {
try {
Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
Object object = clazz.newInstance();
//((Teacher)object).lesson("Mysql", "302", 2);
// 必须提供方法名, 和方法的形参类型列表
// getMethod()只能获取公共方法, 包括父类继承的.
//Method m1 = clazz.getMethod("lesson", String.class, String.class, int.class);
// getDeclaredMethod获取本类中声明的所有方法, 包括私有的.
Method m1 = clazz.getDeclaredMethod("lesson", String.class, String.class, int.class);
m1.setAccessible(true);
// 必须再通过m1调用, 如果方法是void, 它的返回值就是null, 提供实参列表
Object retValue = m1.invoke(object, "MySQL", "302", 3);//object.lesson("Mysql", "302", 2);
System.out.println(retValue);
Method hashCode = clazz.getMethod("hashCode");// 获取父类继承来的公共方法. 方法没有参数, 不需要提供参数列表
System.out.println(hashCode.invoke(object)); // object.hashCode(), 方法没有参数, 也不需要提供实参列表.
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) { // 没有访问权限
e.printStackTrace();
} catch (InstantiationException e) { // 创建对象失败
e.printStackTrace();
} catch (NoSuchMethodException e) { // 没有找到方法.
e.printStackTrace();
} catch (InvocationTargetException e) { // 调用的目标方法出问题时.
e.printStackTrace();
}
}
⑥静态属性的反射
@Test
public void test12() {
try {
Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");
Field school = clazz.getField("school");
school.set(null, "sgg"); // Teacher.school = "sgg";, 第一个参数会被完全忽略
System.out.println(school.get(null)); // 静态属性的访问不需要对象, 所以参数中数据被忽略
Class superclass = clazz.getSuperclass(); // 获取父类
System.out.println(superclass);
Class[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
System.out.println(interfaces[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
}
上一篇: C语言中的全局变量和局部变量区分
下一篇: c语言全局变量
推荐阅读
-
Oracle Java JDBC编程注意事项
-
Failed to convert property value of type ’java.lang.String‘ to required type ‘java.util.Date’…
-
最长公共子序列模板(Java)
-
Java、.Net、PHP、Ruby优劣势概览
-
java软件工程师学php - 5. 变量的“状态”
-
java-mysql语句这样有错误问题出在哪?
-
零基础写Java知乎爬虫之准备工作
-
JAVA工具类——(Collections类和Arrays类)
-
java Collections,Arrays工具类集合
-
Java在Web开发语言上败给了PHP????