修饰符class类名{
1.成员变量(Field:描述类和对象的属性信息的)
2.成员方法(Method:描述类或者对象的行为信息的)
3.构造器(Constructor:初始化一个类的对象并返回引用)
4.代码块
5.内部类
} 只要不是这五大成分放在类下就会报错
修饰符 类名(形参){
}
构造器初始化对象格式:类名 对象名 = new 构造器;
this代表了当前对象的引用。
this关键字可以用在实例方法和构造器中。
用在方法中,谁调用这个方法,就代表谁。
用在构造器中,代表了构造器正在初始化的那个对象的引用。
面向对象三个特征:封装、继承、多态
封装作用:
1.提高安全性
2.实现代码的组件化
封装规范:
1.成员变量都私有:用private修饰。
2.提供成套的getter+setter方法暴露成员变量的取值和赋值。
3.合理隐藏,合理暴露。
通过static关键字区分成员变量属于类还是属于对象的。
有static修饰的变量也叫类变量属于类本身
有static修饰的方法也叫类方法属于类本身
成员变量访问语法:
静态成员变量访问:类名.静态成员变量
实例成员变量访问:对象.实例成员变量
成员方法访问语法:
静态方法访问:类名.静态方法
实例方法访问:对象.实例方法
public class Demo01 {
public static String SchoolName="四川大学";
private String name;
private int age;
private String sex;
public Demo01(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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 getSex() {return sex;}
public void setSex(String sex) {this.sex = sex;}
public static void inAddr(){
System.out.println("我在四川大学学习。");
}
public void getStudent(){
System.out.println(name+"已经"+age+"岁了");
}
public static void main(String[] args) {
System.out.println(Demo01.SchoolName);
inAddr();
Demo01.inAddr();
Demo01 s=new Demo01("yhh", 22, "男");
s.getStudent();
}
}
一般到特殊的关系,是一种子类到父类的关系,可以提高代码的复用
特点:子类继承一个父类,子类可以直接得到父类的属性(成员变量)和行为(方法)。
子类 extends 父类 {}
@Override
重写后调用父类方法需要中转super:父类引用
子类构造器的第一行默认先访问父类的无参数构造器,在执行子类自己的构造器
子类构造器第一行super();默认存在
子类构造器中可以通过super根据参数调用对应父类构造器
this(…)和super(…)在构造器中使用必须在第一行
1.单继承:一个类只能继承一个直接父类(可能出现代码二义性)
2.多层继承:一个类可以间接继承多个父类
3.一个类可以有多个子类
4.一个类要么默认继承Object类,要么间接继承了Object类
public void go(student a){
a.run();
}
class student{
public void run(){
System.out.println("yhh");
}
}
引用类型作为成员变量(复合类型)
公共父类(类似声明)子类必须实现所有抽象方法
抽象方法——表达概念无法实现具体代码的方法
抽象类——表达概念而无法构造出实体的类
为了被子类继承
体现模板思想,部分实现,部分抽象
一个类继承了抽象类,必须重写全部抽象方法
获得了拥有抽象方法的能力
失去了创建对象的能力(抽象方法不能执行)
其他类的特征都拥有
优秀软件设计架构和思想,后来者可以使用这些架构或者思想设计出优秀、提高效率、提高软件可扩展性和可维护性的软件。
作用:优化代码架构、提高代码复用。
体现规范思想,实现接口的子类必须写完接口的全部抽象方法(接口是彻底的抽象)
接口中抽象方法可以省略关键字(public abstract),常量(public static final)变量值只有一个,程序运行的过程中无法修改
实现类——接口(接口被类实现)
接口与接口多继承
类实现接口的格式:
修饰符 class 实现类名称 implements 接口1,接口2,接口3,…{
}
class pingpongMan implements SportMan,Exit{
@Override
public void run() {
}
@Override
public void competition() {
}
@Override
public void rule() {
}
@Override
public void abroad() {
}
@Override
public void exit() {
}
}
interface SportMan extends Law,Go{
void run();
void competition();
}
interface Law{
void rule();
}
interface Go{
void abroad();
}
interface Exit{
void exit();
}
接口新增三个方法:
默认方法(default:由实现接口类对象调用)静态方法(static:只能由实现类名调用)私有方法(private:给私有和默认方法调用)
实现多个接口中同名的静态方法不会冲突
子类继承一个父类又实现多个接口时,成员方法与默认方法重名,子类优先执行父类的成员方法
一个类实现多个接口时,接口中存在同名的默认方法时必须重写这个方法
接口:可以多实现
抽象类:只能被一个类继承
格式:static{}
必须用static修饰,属于类,会与类一起优先加载,而且自动触发执行一次。
可以用于执行类的方法之前进行静态资源的初始化操作。
格式:{}
必须无static修饰,属于类的每个对象,会与类的每个对象一起加载,每次创建对象的时候自动触发执行一次。
作用:初始化实例资源
实例代码块提到构造器中执行的
final可以用于修饰类、方法、变量
(1)final修饰类:类不能被继承
(2)final修饰方法:方法不能被重写
(3)final修饰变量:变量有且只能被赋值一次
abstract和final的关系?互斥关系,不能同时出现。
让值被保护起来,执行的过程中防止被修改。
变量变成常量(常量一般公开)
单例:一个类永远只存在一个对象,不能创建多个对象
单例实现方式(8种):目前两种饿汉、懒汉
通过类获取单例对象时,对象已经提前创建好
实现步骤:1.定义一个单例类
2.把类的构造器私有
3.定义一个静态成员变量用于存储一个对象
4.定义一个方法返回单例对象
public class SingleInstanceDemo01 {
public static SingleInstanceDemo01 ins=new SingleInstanceDemo01();//在此处调用构造器创建对象
private SingleInstanceDemo01(){
}
public static SingleInstanceDemo01 getInstance(){
return ins;
}
public static void main(String[] args) {
SingleInstanceDemo01 s1=SingleInstanceDemo01.getInstance();
SingleInstanceDemo01 s2=SingleInstanceDemo01.getInstance();
System.out.println(s1==s2);
}
}
通过类获取单例对象的时候发现没有对象才去创建一个对象
实现步骤:1.定义一个单例类
2.把类的构造器私有
3.定义一个静态成员变量用于存储一个对象
4.定义一个方法返回单例对象,判断对象不存在才创建一次,对象存在则直接返回
public class SingleInstanceDemo02 {
public static SingleInstanceDemo02 ins;
private SingleInstanceDemo02(){
}
public static SingleInstanceDemo02 getInstance(){
if(ins==null){
ins=new SingleInstanceDemo02();
}
return ins;
}
public static void main(String[] args) {
}
}
用于做信息标志和信息分类
格式:
修饰符 enum 枚举名称{
实例1名称,实例2名称,…
}
enum Oritation{
UP,DOWN,LEFT,RIGHT
}
public class EnumDemo {
public static void main(String[] args) {
move(Oritation.UP);
}
public static void move(Oritation oritation){
switch (oritation){
case UP:
System.out.println("上");
break;
case DOWN:
System.out.println("下");
break;
case LEFT:
System.out.println("左");
break;
case RIGHT:
System.out.println("右");
break;
}
}
}
多态的形式:
父类类型 对象名称 =new 子类构造器; 父类类型范围>子类类型范围
接口 对象名称 = new 实现类构造器;
同一个类型的对象,执行同一个行为,在不同状态下表现出不同的行为特征
对于方法的调用:编译看左边,运行看右边
对于变量的调用;编译看左边,运行看左边
1.必须存在继承或者实现关系
2.必须存在父类类型的变量引用子类类型的对象
3.需要存在方法重写
1.在多态的形式下,右边对象可以实现组件化切换,业务能力也随之改变,便于扩展和维护。
2.在实际开发过程中,父类类型作为方法形式参数,传递给子类对象方法,可以传入一切子类对象进行方法的调用。
在多态形式下,不能调用子类独有功能。
引用类型的自动类型转换(小范围对象赋值给大范围的变量)
引用类型的强制类型转换(大范围对象赋值给小范围的变量)可以解决多态劣势
强制类型转换可能出现类型转换异常问题
if (A instanceof Cat){
Cat c1=(Cat) A;
}
项目示例
public class PolymorphicDemo {
public static void main(String[] args) {
Computer c=new Computer();
USB xiaomi=new Mouse("小米");
c.installUSB(xiaomi);
USB lg=new KeyBoard("罗技");
c.installUSB(lg);
}
}
class Computer{
public void installUSB(USB usb){
//usb可能是鼠标或者键盘
usb.connect();
if(usb instanceof Mouse){
Mouse m=(Mouse) usb;
m.DoubleClick();
}else if (usb instanceof KeyBoard){
KeyBoard k=(KeyBoard) usb;
k.keyDown();
}
usb.unconnect();
}
}
class Mouse implements USB{
private String name;
Mouse(String name) {
this.name = name;
}
public void DoubleClick(){
System.out.println("双击");
}
@Override
public void connect() {
System.out.println(name+"成功接入了设备");
}
@Override
public void unconnect() {
System.out.println(name+"成功拔出了设备");
}
}
class KeyBoard implements USB{
private String name;
KeyBoard(String name) {
this.name = name;
}
public void keyDown(){
System.out.println(name+"写下了");
}
@Override
public void connect() {
System.out.println(name+"成功接入了设备");
}
@Override
public void unconnect() {
System.out.println(name+"成功拔出了设备");
}
}
//定义USB规范,必须完成接入和拔出
interface USB{
void connect();
void unconnect();
}
定义在一个类内部
可以提供更好的封装性,内部类具有更多权限修饰符,封装性具有更多的控制
static修饰,属于外部类本身,只会加载一次
**访问:**外部类名称.内部类名称
**创建:**外部类名称.内部类名称 对象名称=new 外部类名称.内部类构造器;
无static修饰,属于外部类的对象
**访问:**外部类名称.内部类名称
**创建:**外部类名称.内部类名称 对象名称=new 外部类构造器.new 内部类构造器;
定义在方法中,构造器中,代码块中,for循环中的内部类
只能定义实例成员和常量
目的:简化代码
格式:
new 类名|抽象类|接口(形参){
方法重写
};
特点:1.没有名字的内部类
2.一旦写出来就立即创建一个匿名内部类的对象返回
3.匿名内部类的对象类型相当于是当前new的那个类型的子类型
开发常见形式
public class Anonymity {
public static void main(String[] args) {
Swim yhh= () -> System.out.println("yhh is swimming good!");
go(yhh);
go(new Swim() {
@Override
public void swimming() {
System.out.println("yhh is swimming good!");
}
});
}
public static void go(Swim s){
System.out.println("start");
s.swimming();
System.out.println("end");
}
}
interface Swim{
void swimming();
}
命名规范:
公司域名的倒写+技术名称(全部使用英文)
相同包下的类可以直接访问,不同包下的类需要导包才能使用
1.直接调用返回对象在内存中的地址
2.开发中直接输出对象变量的地址信息是无意义的,因此需要重写toString()
1.默认比较两个对象的地址是否相同
2.比较内容是否相同
重写步骤:
1.判断类型
2.判断内容是否相同
Objects.equals(Object a, Object b)
1.创建一个日期对象代表了系统此刻日期时间
2.时间毫秒值,可以用作为时间的计算
3.有参构造器.时间毫秒值转换为时间对象
Date d=new Date();
System.out.println(d);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
String rs =sdf.format(d);
System.out.println(rs);
1.定义字符串时间
2.把字符串时间解析成Date日期对象(创建一个SimpleDateFormat类对象利用parse())
3.得到日期对象时间毫秒值
4.把时间毫秒值格式化为喜欢的字符串时间格式
String date="2022-04-09 10:10:30";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date1=sdf.parse(date);
long time=date1.getTime()+(24L*60*60+15*60*60+30*60+29)*1000;
System.out.println(sdf.format(time));
// 单例方式获取日历对象
Calendar rigjtNow= Calendar.getInstance();
// 日历获取年份等等
int year=rigjtNow.get(Calendar.YEAR);
// 日历修改年份
rigjtNow.set(Calendar.YEAR, 2023);
// 日历获取日期对象
Date d=rigjtNow.getTime();
// 日历获取时间毫秒值
long time=rigjtNow.getTimeInMillis();
// 701天后是那个日期
rigjtNow.add(Calendar.DAY_OF_YEAR, 701);
Math.abs(-10);//绝对值
Math.ceil(4.1);//向上取整
Math.floor(4.9);//向下取整
Math.pow(2, 3);//指数次方
Math.round(4.5);//四舍五入
System.exit(0);//0表示正常终止
long time =System.currentTimeMillis();//得到当前时间毫秒值
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(time));
System.arraycopy();//数组拷贝
double a=0.1;
BigDecimal a1=BigDecimal.valueOf(a);
自动装箱、自动拆箱
包装类可以存储null
把字符串类型的数值转换成对应的基本数据类型的值
String str="23";
int numInt=Integer.valueOf(str);
正则表达式做校验
任何字符
\d 数字: [0-9]
\D非数字:[^0- 9]
\s空白字符: [ \t\n\xOB\f\r]
\S非空白字符: [^\5]
\w单词字符: [a-zA-z_ 0-9]
\W非单词字符: [^\W]
Greedy数量词
X? X, 一次或一次也没有
X* X, 零次或多次
X+ X, 一次或多次
X{n}X, 恰好n次
X{n,}X,至少n次
X{n,m}X,至少n次,但是不超过m次
public static boolean checKEmailRegex(String qq){
return qq!=null&&qq.matches("\\w{1,}@\\w{2,10}(\\.\\w{2,10}){1,2}");
}
//分割
String name="yhh,zhy,lbw";
String[] nameArrs=name.split(",");
//替换
String name="yhh,zhy,lbw";
System.out.println(name.replaceAll(",+", "/"));
1.定义爬取规则
2.把正则表达式进行编译成为一个匹配规则对象
3.通过匹配规则对象得到一个匹配数据内容的匹配器对象
4.通过匹配器去内容中爬取出信息
String name="yhh,zhy,lbw";
String regex="\\w{3,10}";
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(name);
while (matcher.find()){
System.out.println(matcher.group());
}
泛型没有继承关系
泛型就是一个标签:<数据类型>
ArrayList<String> lists=new ArrayList<>();
泛型:约束了操作的数据类型,从而不会出现类型转换异常
类:修饰符 class 类名 <数据类型>{}
方法:修饰符 <泛型变量> 返回值类型 方法名称(形参列表){}
泛型做通用技术架构
修饰符 interface 接口名称 <泛型变量>{}
public interface Data<T>{
void add(T name);
void delete(T name);
void update(T name);
int query(T id);
}
?可以在使用泛型的时候代表一切类型
泛型的上下限(?必须是子类或者其父类)
集合是一个大小可变的容器
数组:类型和长度定义时被确定
Iterator<String> it =lists.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
for (String s:lists){
System.out.println(s);
}
lists.forEach(s-> System.out.println(s));
lists.forEach(System.out::println);
先进后出,后进先出。手枪弹夹
先进先出,后进后出。各种排队叫号系统
元素存在索引(查询快、增删慢)
不是连续存储区域(数据域、地址域)
查询慢、增删快
可能出现瘸子现象
不要让树过高(左右子树高度差绝对值不能超过1)
旋转算法:提高结点
就是平衡的二叉查找树
底层基于数组
遍历方式四种
ArrayList<String> lists=new ArrayList<>();
//在某个索引位置插入元素
lists.add(2,"MySQL");
System.out.println(lists);
//根据索引删除元素,并返回该元素
System.out.println(lists.remove(2));
//根据索引获取元素
System.out.println(lists.get(2));
//修改索引位置处元素
lists.set(1, "java3");
底层基于链表
//创建队列
LinkedList<String> queue=new LinkedList<>();
//入队
queue.addLast("1");
queue.addLast("2");
System.out.println(queue);
//出队
System.out.println(queue.removeFirst());
System.out.println(queue);
//做一个栈
LinkedList<String> stack=new LinkedList<>();
//压栈
stack.push("1");
stack.push("2");
stack.push("3");
System.out.println(stack);
//弹栈
System.out.println(stack.pop());
System.out.println(stack);
//经典代码,无序的
Set<String> sets=new HashSet<>();
无序的原因
如果认为内容重复就重复了,那么必须重写hashCode和equals
有序不重复,额外添加了链来维护添加顺序
默认大小升序排列不重复
自排序方式:
1.有值自动排序
2.首字符编号
3.引用数据类型(1.引用类型定义Comparable 2.为集合定义比较器Comparable )
private static void sortCards(List<Card> cards) {
Collections.sort(cards, new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
return o1.getIndex()-o2.getIndex();
}
});
}
//-----------------------------------------------------
private static void sortCards(List<Card> cards) {
Collections.sort(cards, (o1, o2) -> o1.getIndex()-o2.getIndex());
}
//------------------------------------------------------
private static void sortCards(List<Card> cards) {
Collections.sort(cards, Comparator.comparingInt(Card::getIndex));
}
用来操作集合的工具类
Collections.addAll(apples, a1,a2,a3);
Collections.sort(apples);
Collections.shuffle(apples);
本质上是一个数组
只能有一个,且必须放最后面
sum();
sum(10);
sum(10,20,30,40);
sum(new int[] {10,20,30,40});
public static void sum(int... nums){
}
Map集合(双列集合,一个元素两个值元素格式,key=value)
都可以存入自定义数据类型
List<String> names=new ArrayList<>();//有序可重复,有索引
names.add();
names.size();
names.get();
Set<String> names=new HashSet<>();//无序不重复,无索引
names.add();
names.size();
Map<String,String> names=new HashMap<>();//无序不重复,无索引
Map集合的完整元素{key1=value1,key2=value2,……}
Map集合适合做购物车这样的系统(键值对数据)
与Set集合底层一致
特点:
1.无序,不重复,无索引
2.重复键对应元素会覆盖前面整个元素
3.对于值无要求
HashMap:无序不重复,无索引
LinkedHashMap:无序可重复,无索引
Map<String,String> names=new HashMap<>();//无序不重复,无索引
//添加元素
names.put("娃娃", "123");
//清空集合
// names.clear();
//判断是否为空
names.isEmpty();
//根据键获取值
names.get("娃娃");
//根据键删除整个元素
names.remove("yijia");
//是否包含某个键或值
names.containsKey("娃娃");
names.containsValue("123");
//获取全部键Set或者值Collection的集合
Set<String> keys=names.keySet();
Collection<String> values=names.values();
//集合的大小
names.size();
//合并其他Map集合
Map<String,String> maps1=new HashMap<>();
maps1.put("yh", "12");
names.putAll(maps1);
先获取键的集合Set在通过遍历键找值
将键值对作为一个整体遍历,但键值对没有直接数据类型
//获取键值对集合
Set<Map.Entry<String, String>> entries = names.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
此时键值对作为一个实体类型
names.forEach((k,v)-> System.out.println(k+"=>"+v));
有序不重复
LinkedHashSet基于LinkedHashMap去掉值
有排序不重复
TreeSet基于TreeMap去掉值
package test02;
import java.util.*;
/**
* @Author yehonghan
* @2022/4/10 13:38
*/
public class BookSystem {
//定义一个集合用于图书馆储存书本信息
public static final Map<String, List<Book>> BOOK_STORE = new HashMap<>();
public static final Scanner SYS_SCANNER=new Scanner(System.in);
//
public static void main(String[] args) {
//展示操作界面
showCommand();
}
private static void showCommand() {
System.out.println("===================欢迎进入系统==================");
System.out.println("=============(1)查看全部书籍 query==============");
System.out.println("=============(2)添加书籍信息 add================");
System.out.println("=============(3)删除书籍信息 delete=============");
System.out.println("=============(4)修改书籍信息 update=============");
System.out.println("==============(5)退出系统 exit==================");
System.out.print("请您输入您的操作:");
String command=SYS_SCANNER.nextLine();
//判断命令
switch (command){
case "query":
queryBooks();
break;
case "add":
AddBook();
break;
case "delete":
deleteBooks();
break;
case "update":
updateBooks();
break;
case "exit":
System.out.println("退出成功!!!");
System.exit(0);
break;
default:
System.err.println("您输入的命令无效,请重新输入:");
}
showCommand();
}
private static void updateBooks() {
queryBooks();
System.out.println("===========开始修改书本信息============");
while(true){
System.out.println("请输入修改书本栏目:");
String type=SYS_SCANNER.nextLine();
if(BOOK_STORE.containsKey(type)){
while (true){
System.out.println("请输入修改书本名称:");
String name=SYS_SCANNER.nextLine();
Book book=getBookByTypeAndName(type,name);
if(book==null){
System.err.println("您输入的书名不存在,请重新确认!");
}else {
System.out.println("请您输入添加书本名称:");
String newname=SYS_SCANNER.nextLine();
System.out.println("请您输入添加书本价格:");
String newprice=SYS_SCANNER.nextLine();
System.out.println("请您输入添加书本作者:");
String newauthor=SYS_SCANNER.nextLine();
book.setName(newname);
book.setPrice(Double.valueOf(newprice));
book.setAuthor(newauthor);
return;
}
}
}else {
System.out.println("您输入的栏目不存在,请重新确认!");
}
}
}
private static Book getBookByTypeAndName(String type,String name){
List<Book> books=BOOK_STORE.get(type);
for (Book book : books) {
if(book.getName().equals(name)){
return book;
}
}
return null;
}
private static void deleteBooks() {
if(BOOK_STORE.size()==0){
System.out.println("您的图书馆一本书都没有,请快去买书吧!");
}else {
queryBooks();
while (true){
System.out.println("请输入您要删除的书籍类型");
String type=SYS_SCANNER.nextLine();
if(BOOK_STORE.containsKey(type)){
while (true){
System.out.println("请输入删除书籍名称:");
String name=SYS_SCANNER.nextLine();
Book book=getBookByTypeAndName(type, name);
if (book==null){
System.out.println("没有该书籍名称,是否退出y?");
String ch=SYS_SCANNER.nextLine();
if(ch.equals("y")){
return;
}
}else {
List<Book> books=BOOK_STORE.get(type);
// book.setName("");
// book.setPrice(Double.valueOf(""));
// book.setAuthor("");
books.remove(book);
System.out.println("删除成功!");
return;
}
}
}else {
System.out.println("没有该书籍类型,是否退出y?");
String ch=SYS_SCANNER.nextLine();
if(ch.equals("y")){
return;
}else {}
}
}
}
}
private static void queryBooks() {
if(BOOK_STORE.size()==0){
System.out.println("您的图书馆一本书都没有,请快去买书吧!");
}else{
System.out.println("===========查看所有书籍====================");
System.out.println("类型\t\t\t\t\t书名\t\t\t\t\t 价格\t\t\t作者");
BOOK_STORE.forEach((type,books)->{
System.out.println(type);
for (Book book : books) {
System.out.println("\t\t\t\t\t"+book.getName()+"\t\t\t\t"+book.getPrice()+"\t\t\t"+book.getAuthor());
}
});
}
}
private static void AddBook() {
System.out.println("==========开始添加书籍===========");
System.out.println("请您输入添加书本栏目:");
String type=SYS_SCANNER.nextLine();
List<Book> books;
//判断是否存在栏目
if(BOOK_STORE.containsKey(type)){
//存在该栏目
books=BOOK_STORE.get(type);
}else{
books=new ArrayList<>();
BOOK_STORE.put(type, books);
}
System.out.println("请您输入添加书本名称:");
String name=SYS_SCANNER.nextLine();
double PriceDouble;
while (true){
try {
System.out.println("请您输入添加书本价格:");
String price=SYS_SCANNER.nextLine();
PriceDouble= Double.valueOf(price);
break;
}catch (Exception e){
System.err.println("输入的价格不对!");
}
}
System.out.println("请您输入添加书本作者:");
String author=SYS_SCANNER.nextLine();
Book book=new Book(name,PriceDouble, author);
books.add(book);
System.out.println("您添加在"+type+"下的书本"+book.getName()+"成功!");
}
}
for(int i=0;i<arr.length-1;i++){
for (int j = 0; j < arr.length-i-1; j++) {
if(arr[j]>arr[j+1]){
int temp;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for(int i=0;i<arr.length-1;i++){
for (int j = i+1; j < arr.length; j++) {
int temp;
if(arr[i]>arr[j]){
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
public static int BinarySerach(int[] nums,int number){
int left=0;
int right=nums.length-1;
int mid=(left+right)/2;
while (left!=right){
if(nums[mid]>number){
right=mid-1;
}else {
left=mid+1;
}
mid=(left+right)/2;
if (number==nums[mid]){
return mid;
}
}
return -1;
}
异常:编译或者执行过程中出现的问题
java中异常继承的类是Throwable
Error Exception(异常,需要研究和处理)
编译时异常,运行时异常
//数组索引越界
int[] nums={2};
System.out.println(nums[1]);
//空指针异常
String name=null;
System.out.println(name.length());
//类型转换异常
Object o="齐天大神";
Integer s=(Integer) o;
//迭代器遍历没有此元素
//数学操作异常
int c=10/0;
//数字转换异常
String num="23aa";
Integer it=Integer.valueOf(num);
提醒程序员可能会出错,编译时必须处理
出现异常,创建异常对象,返回异常信息给调用者,JVM打印异常栈信息,关闭程序
1.抛出异常:
与默认异常类似
方法 throws 异常1,异常2{}
方法 throws Exception{}
2.捕获处理:
try{
}catch(Exception e){
e.printStackTrace();
有异常做什么处理}
3.异常一层层抛出最外层集中处理
应该避免,捕获异常即可
最终一定要执行,可以在代码执行完毕后进行资源的释放
需要继承异常接口Exception,并重写构造器,在使用出抛出
class OpenException extends Throwable{ }
class CloseException extends OpenException{ }
public class TryCatchTest {
public static int open(){
return -1;
}
public static void readFile() throws OpenException {
if(open()==-1){
throw new CloseException();
}
}
public static void main(String[] args) {
try {
readFile();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (OpenException e) {
e.printStackTrace();
System.out.println("close");
}
}
}
可以处理代码问题,防止程序出现异常后死亡
提高程序健壮性和安全性
线程是属于进程中的一个独立运行单元,一个进程可以包含多个线程,这就是多线程。
线程创建开销相对于进程来说比较小,线程也支持并发。
1.定义一个类继承线程类Thread,重写run方法,创建线程对象并调用start方法启动。
优点:编码简单
缺点:无法继承其他类,功能单一
2.定义一个线程任务类实现Runnable接口,重写run方法,创建线程任务对象,再把线程任务对象包装成线程对象,调用start方法启动。
优点:实现接口,可以继承其他类,功能可以增强,同一个线程任务对象可以被包装成多个线程对象
实现解耦任务代码与线程独立
缺点:复杂一点
public class ThreadDemo02 {
public static void main(String[] args) {
//创建任务对象
Runnable target=new MyRunnable();
//包装成线程对象
Thread t1=new Thread(target,"1号线程");
t1.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"==》"+i);
}
}
}
//-----------------------------------------------
//匿名内部类写法
new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "==》" + i);
}
}).start();public class ThreadDemo02 {
public static void main(String[] args) {
new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "==》" + i);
}
}).start();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "==》" + i);
}
}
}
3.实现Callable接口
前面所有优点
public class ThreadDemo02 {
public static void main(String[] args) {
//创建call对象
Callable<String> call=new MyCallable();
//保存成任务对象
FutureTask<String> task=new FutureTask<>(call);
//包装成线程对象
Thread t=new Thread(task);
t.start();
for (int i = 0; i < 11; i++) {
System.out.println(Thread.currentThread().getName()+"=>"+i);
}
try {
String rs=task.get();
System.out.println(rs);
}catch (Exception e){
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String>{
@Override
public String call() throws Exception {
int sum=0;
for (int i = 0; i < 11; i++) {
System.out.println(Thread.currentThread().getName()+"=>"+i);
sum+=i;
}
return Thread.currentThread().getName()+"执行结果是:"+sum;
}
}
t1.setName("1号线程");//可以通过有参构造器取名
t1.getName();
Thread.currentThread();//返回当前运行的线程
Thread.sleep(1000);//当前线程停止一秒
多个线程同时操作一个共享资源的时候可能出现线程安全问题:比如同时修改或删除等操作
可能出现问题代码上锁,每次只能一个线程进入,执行完毕自动解锁。
synchronized (锁唯一对象){
//核心代码
}
方法名上加入synchronized
//创建一个lock对象
private final Lock lock=new ReentrantLock();
String name = Thread.currentThread().getName();
lock.lock();
try {
if (this.money >= i) {
System.out.println(name + "来取钱,取出" + i);
this.money -= i;
System.out.println(name + "来取钱后,剩余" + this.money);
} else {
System.out.println(name + "来取钱,余额不足。");
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
核心方法与实例DAY03_test05
lock.wait();//让当前线程进入等待状态
lock.notify();//唤醒锁对象上的某个线程
lock.notifyAll();//唤醒锁对象上的所有线程
新建(new)线程对象没有线程特征
就绪和运行(t.start)
终止(Teminated)
锁阻塞(Blocked)
无限等待(Waiting)
计时等待(Timed Waiting)
线程池是容纳多个线程的容器,其中线程可以反复使用
1.减低资源消耗
2.提高相应速度
3.提高线程可管理性
//1定义任务类----------------------------------
class MyRunable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"==>"+i);
}
}
}
//2创建线程池
ExecutorService pools= Executors.newFixedThreadPool(3);
//3创建任务
Runnable t=new MyRunable();
//4将任务交给线程池
pools.submit(t);
//5关闭线程池--------------------------------------
pools.shutdown();
//Callable创建线程池
public class ThreadPoolsDemo {
public static void main(String[] args) {
ExecutorService pools= Executors.newFixedThreadPool(3);
Callable t1=new MyCallable(10);
Callable t2=new MyCallable(15);
Callable t3=new MyCallable(20);
Future<String> f1=pools.submit(t1);
Future<String> f2=pools.submit(t2);
Future<String> f3=pools.submit(t3);
try {
String rs1=f1.get();
String rs2=f2.get();
String rs3=f3.get();
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n){
this.n=n;
}
@Override
public String call() throws Exception {
int sum=0;
for (int i = 0; i < n; i++) {
sum+=i;
}
return Thread.currentThread().getName()+"==>"+sum;
}
}
1.互斥使用
2.不可抢占
3.请求和保持
4.循环等待
new Thread(new Runnable(){
@Override
public void run() {
}
}).start();
//多个线程访问共享变量后,一个线程修改变量后,其他线程不可见
//JMM模型Java内存模型为多线程服务
//共享变量在主内存中,线程运行时拷贝到线程的工作内存中
//每个线程拥有工作内存
//加锁会清空工作内存
1.加锁synchronized
2.Volatile只能修饰实例变量和类变量(只是保证数据可见性)
private volatile boolean flag=false;//更改后通知其他工作内存变量失效
//Volatile只能保证线程可见性不能保存原子性
//加锁可以保证原子性
//创建原子对象
private AtomicInteger atomicInteger=new AtomicInteger();
//CAS(先比较再交换)读写
CAS(乐观锁) Atomiclnteger
synchronized(悲观锁)
java官方提供的了性能优异且线程安全的并发包
HashMap在高并发情况下不安全
HashTable(全部加锁)线程安全,但性能较差已经淘汰
可以使用ConcurrentHashMap(局部加锁)线程安全且综合性能好CAS
long time=System.currentTimeMillis();
用于监督控制线程流转
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch c=new CountDownLatch(1);//计数可以完成多步唤醒机制
new ThreadA(c).start();
new ThreadB(c).start();
}
}
class ThreadA extends Thread{
private CountDownLatch c;
public ThreadA(CountDownLatch c) {
this.c=c;
}
@Override
public void run() {
super.run();
System.out.println("A");
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("C");
}
}
class ThreadB extends Thread{
private CountDownLatch c;
public ThreadB(CountDownLatch c) {
this.c=c;
}
@Override
public void run() {
super.run();
System.out.println("B");
c.countDown();
}
}
循环屏障对象保证其他线程完成后触发一次线程任务
用于多个线程进行操作,最后汇总
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier c=new CyclicBarrier(5,new meeting());
for (int i = 0; i <5; i++) {
new EmployeeThread("员工"+i,c).start();
}
}
}
class meeting implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始组织会议!");
}
}
class EmployeeThread extends Thread{
private CyclicBarrier c;
public EmployeeThread(String s, CyclicBarrier c) {
super(s);
this.c=c;
}
@Override
public void run() {
super.run();
try {
System.out.println(Thread.currentThread().getName()+"正在进入会议室");
Thread.sleep(3000);
c.await();
}catch (Exception e){
e.printStackTrace();
}
}
}
控制线程的并发数量(相当于锁多个,先到先执行)
public class SemaphoreDemo {
public static void main(String[] args) {
MySemaphor mySemaphor=new MySemaphor();
for (int i = 0; i < 5; i++) {
Thread a=new MyThread(mySemaphor);
a.setName("线程"+i);
a.start();
}
}
}
class MySemaphor {
private Semaphore semaphore=new Semaphore(1);
public void login(){
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"进入时间="+System.currentTimeMillis());
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"登录成功!");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"离开时间"+System.currentTimeMillis());
semaphore.release();
}
}
class MyThread extends Thread{
private MySemaphor mySemaphor;
public MyThread(MySemaphor mySemaphor) {
this.mySemaphor=mySemaphor;
}
@Override
public void run() {
super.run();
mySemaphor.login();
}
}
用于线程间协作的工具类用于线程之间数据交流
public class ExchangerDemo {
public static void main(String[] args) {
Exchanger<String> exchanger=new Exchanger<>();
new Boy(exchanger).start();
new Girl(exchanger).start();
}
}
class Boy extends Thread{
private Exchanger<String> exchanger;
public Boy(Exchanger<String> exchanger) {
this.exchanger=exchanger;
}
@Override
public void run() {
super.run();
System.out.println("男孩送了锁");
try {
String rs=exchanger.exchange("锁");
System.out.println("男孩收到礼物"+rs);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Girl extends Thread{
private Exchanger<String> exchanger;
public Girl(Exchanger<String> exchanger) {
this.exchanger=exchanger;
}
@Override
public void run() {
super.run();
System.out.println("女孩准备了钥匙");
try {
String rs=exchanger.exchange("钥匙");
System.out.println("女孩收到礼物"+rs);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
简化匿名内部类的代码写法
格式:
(匿名内部类被重写方法的形参列表)->{
被重写方法的具体代码
(如果代码只有一行1.省略大括号和分号 2.return需要省略 3.参数类型可以不写 4.如果只有一个参数,括号可以省略 )
};
//简化Runable
Thread t=new Thread(()-> System.out.println(Thread.currentThread().getName()+"执行"));
//简化Comparator
Collections.sort(list,new Comparator<Student>(){
@Override
public int compare(Student s1, Student s2) {
return s1.getAge()- s2.getAge();
}
});
public class LambdaDemo {
public static void main(String[] args) {
Thread t=new Thread(()->System.out.println(Thread.currentThread().getName() + "执行"));
t.start();
List<Student> list=new ArrayList<>();
Student s1=new Student("yhh", 18, '男');
Student s2=new Student("yh", 19, '男');
Student s3=new Student("y", 20, '男');
Collections.addAll(list, s1,s2,s3);
Collections.sort(list,(Student o1, Student o2) -> s1.getAge()- s2.getAge());
}
}
class Student{
private String name;
private int age;
private char sex;
public Student(String name, int age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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 char getSex() {return sex;}
public void setSex(char sex) {this.sex = sex;}
}
只能简化接口中只有一个抽象方法的匿名内部类写法
进一步简化Lambda表达式
关键语法::
// lists.forEach(s-> System.out.println(s));
// lists.forEach(System.out::println);
前后参数一样可以使用静态方法引用
// Collections.sort(list,( o1, o2) -> s1.getAge()- s2.getAge());
// Collections.sort(list,Student::CompareByAge);
public static int CompareByAge(Student o1,Student o2){
return o1.getAge()-o2.getAge();
}
// lists.forEach(s-> System.out.println(s));
// lists.forEach(System.out::println);
特定类型::方法
Arrays.sort(list,new Comparator<String>(){
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(s2);
}
});
//--------------------------------
Arrays.sort(list,String::compareToIgnoreCase);
//构造器引用
//格式:类名::new
s->new Student
Student::new
用于解决集合和数组的API弊端
List<String> list=new ArrayList<>();
list.add("张三丰");
list.add("张三");
list.add("李三丰");
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(System.out::println);
//获取stream流
Stream<String> str=list.stream();
Stream<Map.Entry<String,Integer>> map=map.entrySet().stream();
Stream<String> arrs1=Stream.of(arrs);
forEach //foreach遍历
count //统计个数
filter //过滤元素
limit //取前几个元素
skip //跳过前几个
map //加工方法 把原来元素加工然后重新放上去
concat //合并流
将stream流转回集合数组
Stream<String> list1=list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3);
List<String> list2=list1.collect(Collectors.toList());
System.out.println(list2);
代表操作系统的文件对象
是用来操作操作系统的文件对象的,删除、获取、创建文件。
使用正斜杠/
使用反斜杠\
使用分隔符API:File.separator
创建文件对象:使用绝对路径:无法跨平台
**相对路径:**寻找过程目录下文件
f.getAbsolutePath();
f.getPath();
f.getName();
f.length();
//获取文件最后修改时间
long time=f.lastModified();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(time));
f.exists();
f.isFile();
f.isDirectory();
f.createNewFile();
f.delete();
f.mkdir();
f.mkdirs();
f.list();
File[] files=f.listFiles();//获取一级文件目录下文件对象
递归三要素
1.递归终结点;
2.递归公式;
3.递归方向
public class RecursionDemo {
public static void main(String[] args) {
SearchFile(new File("D:/study"), "j1.png");
}
public static void SearchFile(File dir, String fileName){
//判断是否是文件夹
if(dir.exists()&&dir.isDirectory()){
//提取当前目录下的全部一级文件对象
File[] files=dir.listFiles();
//是否为空目录
if(files!=null&&files.length>0){
//遍历一级文件对象
for (File file : files) {
if(file.isFile()){
//是文件判断名称
if(file.getName().contains(fileName)){
System.out.println(file.getAbsolutePath());
//启动exe文件
Runtime r=Runtime.getRuntime();
try {
r.exec(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
}else{
//是文件夹递归调用
SearchFile(file, fileName);
}
}
}
}
}
}
字节输入流 字节输出流 字符输入流 字符输出流
InputStream OutputStream Reader Writer (抽象类)
FileInputStream FileOutputStream FileReader FileWriter (实现类,低级流)
BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter (实现类,缓冲流)
InputStreamReader OutputStreamWriter 实现类转换流)
ObjectInputStream ObjectOutputStream (实现类,序列化流)
PrintStream PrintWriter (实现类,打印流)
按照字节读取文件数据到内存,性能极差
//按照一个字节读
InputStream inputStream=new FileInputStream(file);
int code1=inputStream.read();
System.out.println((char)code1);
//使用循环读
int ch;
while ((ch=inputStream.read())!=-1){
System.out.println((char) ch);
}
//按照字节数组读取
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
byte[] buffer=new byte[3];
//读取字节放入数组中返回读取字节数量
int len=inputStream.read(buffer);
System.out.println(len);
//读了多少倒出多少
String rs=new String(buffer,0,len);
System.out.println(rs);
//使用循环读
//读取字节放入数组中返回读取字节数量
int len;
while ((len=inputStream.read(buffer))!=-1){
String rs=new String(buffer,0,len);
System.out.println(rs);
}
//一次读所有字节
File file=new File("C:\\Users\\86152\\Desktop\\1.txt");
InputStream inputStream=new FileInputStream(file);
file.length();
byte[] buffer=new byte[(int) file.length()];
//读入字节进入数组并返回读入长度
int len=inputStream.read(buffer);
System.out.println(len);
String rs=new String(buffer,0,len);
System.out.println(rs);
//现有API
byte[] buffer=inputStream.readAllBytes();
String rs=new String(buffer,0,len);
System.out.println(rs);
默认是数据覆盖管道
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt");
outputStream.write(97);
outputStream.write('b');
//添加换行方法
outputStream.write("\r\n".getBytes(StandardCharsets.UTF_8));
byte[] bytes="java是真的很牛!".getBytes(StandardCharsets.UTF_8);
outputStream.write(bytes,0,7);
outputStream.flush();
outputStream.close();
//--------------------------------------------------------------------追加数据管道
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt",true);
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt");
byte[] buffer=new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
System.out.println("复制完成!");
inputStream.close();
outputStream.close();
try (
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt",true)
){
byte[] buffer=new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
//单个字符读取
Reader reader=new FileReader("C:\\Users\\86152\\Desktop\\1.txt");
int code=reader.read();
System.out.println((char)code);
//循环读取
int ch;
while ((ch=reader.read())!=-1){
System.out.println((char)ch);
//数组读
char[] chars=new char[1024];
//读入字符进入数组并返回读入长度
int len;
while ((len=reader.read(chars))!=-1){
String rs=new String(chars,0,len);
System.out.println(rs);
Writer writer=new FileWriter("C:\\Users\\86152\\Desktop\\2.txt");
writer.write("叶宏汉");//可以写字符串
writer.write("加油!".toCharArray());//可以写字符数组
//-------------------------------------------------------------------复制文件
try(
Reader reader=new FileReader("C:\\Users\\86152\\Desktop\\1.txt");
Writer writer=new FileWriter("C:\\Users\\86152\\Desktop\\2.txt",true)
) {
char[] chars=new char[1024];
//读入字符进入数组并返回读入长度
int len;
while ((len=reader.read(chars))!=-1){
String rs=new String(chars,0,len);
writer.write(rs.toCharArray());
System.out.println("复制成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
将低级流传入,包装成缓冲流
性能好的原因:先将磁盘文件加载到内存中缓冲池
try (
BufferedInputStream bufferedInputStream=new BufferedInputStream(
new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt"))
){
int len;
byte[] bytes=new byte[1024];
while ((len=bufferedInputStream.read(bytes))!=-1){
String rs=new String(bytes,0,len);
System.out.println(rs);
}
} catch (Exception e) {
e.printStackTrace();
}
数据直接输出到缓冲池
数据直接输入到缓冲池
可以按行读入
public class BufferedStreamDemo {
public static void main(String[] args) {
try (
BufferedReader bufferedReader=new BufferedReader(new FileReader("C:\\Users\\86152\\Desktop\\1.txt"))
){
int len;
char[] bytes=new char[1024];
while (-1 != (len = bufferedReader.read(bytes))){
String rs=new String(bytes,0,len);
System.out.println(rs);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//----------------------------------经典代码------------许多业务需求需要按行读----------------------------------------
try (
BufferedReader bufferedReader=new BufferedReader(new FileReader("C:\\Users\\86152\\Desktop\\1.txt"))
){
String line;
while (null!=(line=bufferedReader.readLine())){
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
数据直接输出到缓冲池
public class BufferedStreamDemo {
public static void main(String[] args) {
try (
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("C:\\Users\\86152\\Desktop\\1.txt",true))
){
bufferedWriter.write("yhh");
bufferedWriter.newLine();
bufferedWriter.write("yh");
} catch (Exception e) {
e.printStackTrace();
}
}
}
解决读取不同编码文件读取乱码问题
BufferedReader bufferedReader1=
new BufferedReader(//字符缓冲输入流
new InputStreamReader(//字符转换输入流
new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt"),"utf-8"));//字节缓冲输入流
BufferedWriter bufferedWriter=
new BufferedWriter(//字符缓冲输出流
new OutputStreamWriter(//字符转换输出流
new FileOutputStream("C:\\Users\\86152\\Desktop\\1.txt"),"utf-8"));//字节缓冲输出流
对象需要序列化必须实现接口Serializable
transient 修饰变量不参与序列化
序列化版本号:序列化和反序列化版本号必须一致
对象序列化:把java对象直接储存到文件中
对象反序列化:把java对象的文件数据恢复到java对象中
字节序列化输出流ObjectOutputStream
ObjectOutputStream objectOutputStream=
new ObjectOutputStream(
new FileOutputStream("C:\\Users\\86152\\Desktop\\2.txt"));
objectOutputStream.writeObject(user);
字节反序列化输入流ObjectInputStream
ObjectInputStream objectInputStream=
new ObjectInputStream(
new FileInputStream("C:\\Users\\86152\\Desktop\\2.txt"));
User user1=(User) objectInputStream.readObject();
System.out.println(user1);
PrintStream printStream=new PrintStream(new FileOutputStream("C:\\Users\\86152\\Desktop\\1.txt"));
//可以直接通向文件但必须覆盖
System.setOut(printStream);//让系统输出流向打印流,直接进入文件
实际上是一个Map集合代表一个属性文件
properties.setProperty("admin", "123456");//保存一对属性
properties.getProperty("admin");//利用键获取属性值
Set<String> set=properties.stringPropertyNames();//获取键名称的集合
properties.store(outputStream, "备注");//保存数据到文件中
properties.load(inputStream);//从文件中读入
//写入属性集文件
public class PropertiesDemo {
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
properties.setProperty("admin", "123456");
System.out.println(properties);
OutputStream outputStream=new FileOutputStream("C:\\Users\\86152\\Desktop\\1.txt");
properties.store(outputStream, "备注");
outputStream.close();
}
}
//读入属性集文件
public class PropertiesDemo {
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
InputStream inputStream=new FileInputStream("C:\\Users\\86152\\Desktop\\1.txt");
properties.load(inputStream);
System.out.println(properties);
inputStream.close();
}
}
public class BeerDemo {
public static void main(String[] args) {
BuyBeer(10);
System.out.println(BeerDemo.totalNum);
}
private static int totalNum;
private static int lastPingZiNum;
private static int lastGaiZiNum;
public static void BuyBeer(int money){
//拿钱买酒
int number=money/2;
//酒的数量
totalNum=totalNum+number;
//当前瓶子与盖子数量
int currentPingZiNum=lastPingZiNum+number;
int currentGaiZiNum=lastGaiZiNum+number;
//能换成多少钱
int totalMoney=0;
totalMoney = totalMoney + (currentGaiZiNum / 4) * 2;
lastGaiZiNum=currentGaiZiNum % 4;
totalMoney = totalMoney + (currentPingZiNum / 2) * 2;
lastPingZiNum=currentPingZiNum % 2;
if(totalMoney>=2) {
BuyBeer(totalMoney);
}
}
}
public class CopyDirDemo {
public static void main(String[] args) {
CopyDir(new File("C:\\Users\\86152\\Desktop\\2"),new File("C:\\Users\\86152\\Desktop\\1"));
}
public static void CopyDir(File srcDir,File destDir) {
if(srcDir.exists()&&srcDir.isDirectory()){
//创建目标文件夹
destDir.mkdirs();
//提取源文件夹一级对象
File[] files=srcDir.listFiles();
if(files!=null&&files.length>0){
for (File file : files) {
if (file.isFile()){
CopyFile(file,new File(destDir,file.getName()));
}
else{
CopyDir(file, new File(destDir,file.getName()));
}
}
}
}
}
private static void CopyFile(File srcfile, File destfile) {
try (
InputStream inputStream=new FileInputStream(srcfile);
OutputStream outputStream=new FileOutputStream(destfile)
){
byte[] buffer=new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
System.out.println("复制完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
C/S架构客户端服务端
B/S架构浏览器和服务器
InetAddress ip=InetAddress.getByName("www.yehonghan.top");
System.out.println(ip.getHostName());//获取域名
System.out.println(ip.getHostAddress());//获取地址
DatagramPacket 数据包对象用来封装要发送或者接受数据
DatagramSocket 用来发送或者接受数据包
public class UDPServerDemo {
public static void main(String[] args) throws Exception {
byte[] buffer=new byte[1024*64];
DatagramPacket datagramPacket=new DatagramPacket(buffer,buffer.length );
DatagramSocket datagramSocket=new DatagramSocket(6666);
datagramSocket.receive(datagramPacket);
String s=new String(buffer,0,datagramPacket.getLength());
System.out.println(s);
System.out.println(datagramPacket.getAddress().getHostAddress());//获取客户端ip
System.out.println(datagramPacket.getPort());//获取客户端端口
datagramSocket.close();
}
}
//----------------------------------------------------------------------------------
public class UDPClientDemo {
public static void main(String[] args) throws IOException {
byte[] buffer="今晚约吗?".getBytes(StandardCharsets.UTF_8);
DatagramPacket datagramPacket=new DatagramPacket(buffer,buffer.length , InetAddress.getLocalHost(),6666 );
DatagramSocket datagramSocket=new DatagramSocket();
datagramSocket.send(datagramPacket);
datagramSocket.close();
}
}
1.客户端要求请求与服务端Socket管道连接
2.从socket通信管道中得到一个字节输出流
3.通过字节输出流给服务端写数据
1.服务端ServerSocket注册端口
2.接受客户端的Socket管道连接
3.从socket中得到一个字节输入流,再读取信息
public class ServerDemo {
public static void main(String[] args) throws Exception {
try (
ServerSocket socket=new ServerSocket(6666);
Socket listensocket=socket.accept();
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(listensocket.getInputStream()))
){
String msg;
if((msg=bufferedReader.readLine())!=null){
System.out.println(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//--------------------------------------------------------
public class ClientDemo {
public static void main(String[] args) {
try (
Socket clientsocket=new Socket("127.0.0.1",6666);
PrintStream printStream=new PrintStream(clientsocket.getOutputStream())
){
//请求连接
printStream.println("我是客户端");
printStream.flush();
System.out.println("发送完毕");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ClientDemo {
public static void main(String[] args) {
System.out.println("-----------客户端启动----------");
try (
Socket clientsocket=new Socket("127.0.0.1",6666);
PrintStream printStream=new PrintStream(clientsocket.getOutputStream())
){
while (true){
Scanner in=new Scanner(System.in);
//请求连接
System.out.println("请说:");
String msg=in.nextLine();
printStream.println(msg);
printStream.flush();
if(msg.equals("exit")){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//-------------------------------------------------------------------------------------
public class ServerDemo {
public static void main(String[] args) throws Exception {
System.out.println("-------服务端启动--------");
try (
ServerSocket socket=new ServerSocket(6666)
){
while (true){
Socket listensocket=socket.accept();
new SocketDemo.MyServerReadThread(listensocket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//-----------------------------------------------------------------
public class MyServerReadThread extends Thread{
private Socket listensocket;
public MyServerReadThread(Socket listensocket) {
this.listensocket = listensocket;
}
@Override
public void run() {
super.run();
try {
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(listensocket.getInputStream()));
String msg;
while (((msg=bufferedReader.readLine())!=null)) {
System.out.println(msg);
if(msg.equals("exit")){
break;
}
}
} catch (IOException e) {
System.out.println("有人下线了!");
e.printStackTrace();
}
}
}
public class ServerExecutorDemo {
public static void main(String[] args) throws Exception {
System.out.println("-------服务端启动--------");
try (
ServerSocket socket=new ServerSocket(6666)
){
ThreadExecutor threadpools =new ThreadExecutor(3,100);
while (true){
Socket listensocket=socket.accept();
System.out.println("有人上线了");
//将任务交给线程池
threadpools.execute(new ReaderClientRunnable(listensocket));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//---------------------------------------------------------------------------
public class ReaderClientRunnable implements Runnable{
private Socket listensocket;
public ReaderClientRunnable(Socket listensocket) {
this.listensocket = listensocket;
}
@Override
public void run() {
try {
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(listensocket.getInputStream()));
String msg;
while (((msg=bufferedReader.readLine())!=null)) {
System.out.println(msg);
if(msg.equals("exit")){
break;
}
}
} catch (IOException e) {
System.out.println("有人下线了!");
}
}
}
//----------------------------------------------------------------------------
public class ThreadExecutor {
private ExecutorService executor;
public ThreadExecutor(int maxPoolSize,int queueSize) {
this.executor = new ThreadPoolExecutor(
//线程池初始线程数
maxPoolSize,
//线程池最多线程数
maxPoolSize,
//任务队列存活时间
120L,
//线程延时时间
TimeUnit.SECONDS,
//任务队列存放Runnable任务
new ArrayBlockingQueue<Runnable>(queueSize));
}
public void execute(Runnable task){
this.executor.execute(task);
}
}
//--------------------------------------------------------------------------------------
public class ClientExecutorDemo {
public static void main(String[] args) {
System.out.println("-----------客户端启动----------");
try (
Socket clientsocket=new Socket("127.0.0.1",6666);
PrintStream printStream=new PrintStream(clientsocket.getOutputStream())
){
while (true){
Scanner in=new Scanner(System.in);
//请求连接
System.out.println("请说:");
String msg=in.nextLine();
printStream.println(msg);
printStream.flush();
if(msg.equals("exit")){
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class BSserverDemo {
public static void main(String[] args) {
try (
ServerSocket serverSocket=new ServerSocket(8080)
){
while (true){
Socket socket=serverSocket.accept();
new ServerReaderThread(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket) {
this.socket=socket;
}
@Override
public void run() {
super.run();
try {
PrintStream printStream=new PrintStream(socket.getOutputStream());
printStream.println("HTTP/1.1 200 OK");
printStream.println("Content-Type:text/html;charset=UTF-8");
printStream.println();
printStream.println("最牛逼的yhh
");
Thread.sleep(10000);
printStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ClientDemo {
public static final String SRC_IMAGE="C:\\Users\\86152\\Desktop\\1\\1.jpg";
public static void main(String[] args) {
try (
Socket socket=new Socket("127.0.0.1",6666);
//获取文件进入字节缓冲输入流
BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(SRC_IMAGE))
){
OutputStream outputStream=socket.getOutputStream();
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(outputStream);
byte[] bytes=new byte[1024];
int len;
while ((len=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
}
bufferedOutputStream.flush();//刷新
socket.shutdownOutput();//通知服务端数据发送完毕
System.out.println("客户端传输图片完毕了!");
//接受相应数据
BufferedReader returnmsg=new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(returnmsg.readLine());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//-------------------------------------------------------------------------------------
public class ServerDemo {
public static void main(String[] args) {
try (
ServerSocket listensocket=new ServerSocket(6666);
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream("C:\\Users\\86152\\Desktop\\2\\"+ UUID.randomUUID() +".jpg"))
){
Socket socket=listensocket.accept();
InputStream inputStream=socket.getInputStream();
BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
byte[] bytes=new byte[1024];
int len;
while ((len=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
}
bufferedOutputStream.flush();
PrintStream printStream=new PrintStream(socket.getOutputStream());
printStream.println("我已经收到你的文件!");
Thread.sleep(1000);
printStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.下载框架jar包
2.a模拟业务代码
b写测试类
c在测试类中写测试方法
d测试方法注意事项:必须public没有返回值宇参数、使用注解@Test
public class UserService {
public String login(String name, String password){
if ("admin".equals(name)&&"123456".equals(password)){
return "success";
}
return "用户名或者密码错误!";
}
}
public class UserServiceTest {
@Test
public void testLogin(){
UserService u=new UserService();
String rs= u.login("admin", "123456");
Assert.assertEquals("您的登录功能有错!","success",rs);
}
}
@before在测试实例方法前执行一次
@after在测试实例方法后执行一次
@BeforeClass在所有测试方法前执行一次
@AfterClass在所有测试方法后执行一次
反射、注解、代理、泛型
反射是指对于任何一个类,在“运行的时候”都可以得到这个类的全部成分。
得到编译后class文件对象
1.反射可以破坏面向对象的封装性,暴力反射
2.同时可以破坏泛型的约束性(泛型只能工作再编译阶段、运行阶段消失)
基于反射技术设计框架
//提供一个方法可以保存一切对象数据的字段
public static void save(Object obj) {
//解析对象的字段和每个字段的值储存起来
try (
PrintStream printStream=
new PrintStream(
new FileOutputStream("C:\\Users\\86152\\Desktop\\1\\1.txt",true))
){
Class c=obj.getClass();
printStream.println("========="+c.getSimpleName()+"============");
//定位它的全部成员变量
Field[] fields=c.getDeclaredFields();
for (Field field : fields) {
//字段名称
String name=field.getName();
//字段的值
field.setAccessible(true);//暴力破解不规范,应该调用get方法
String value=field.get(obj)+"";
printStream.println(name+"="+value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
class:字节码文件类型
Constructor:构造器类型
Field:成员变量的类型
Method:方法类型
public static void main(String[] args) throws ClassNotFoundException {
//类名直接获取
Class c1=Student.class;
System.out.println(c1);
//对象获取
Student s=new Student();
Class c2 = s.getClass();
System.out.println(c2);
//直接加载
Class c3=Class.forName("ReflectionDemo.Student");
System.out.println(c3);
System.out.println(c1.getSimpleName());//获取类名本身
System.out.println(c1.getName());//获取全名
}
//获取public修饰的构造器
@Test
public void getConstructors(){
Class c=Student.class;
Constructor[] cons=c.getConstructors();
for (Constructor con : cons) {
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
}
//无视权限获取全部构造器
@Test
public void getDeclaredConstructors(){
Class c=Student.class;
Constructor[] cons=c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
}
//获取某个构造器
@Test
public void getConstructor() throws Exception {
Class c=Student.class;
//根据参数匹配只能拿public修饰的
Constructor con=c.getConstructor(String.class ,int.class);
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
//无视权限获取按参数匹配
@Test
public void getDeclaredConstructor() throws Exception {
Class c=Student.class;
//根据参数匹配只能拿public修饰的
Constructor con=c.getDeclaredConstructor(String.class ,int.class);
System.out.println(con.getName()+"===>"+con.getParameterCount());
}
@Test
public void Createobj01() throws Exception{
//先得到class对象
Class c=Student.class;
//再获取无参构造器对象
Constructor constructor=c.getDeclaredConstructor();
//将private权限打开
constructor.setAccessible(true);
//通过无参构造器初始化对象返回
Student s=(Student)constructor.newInstance();
System.out.println(s);
s.setName("yhh");
s.setAge(12);
System.out.println(s.getName());
System.out.println(s.getAge());
}
@Test
public void Createobj02() throws Exception{
//先得到class对象
Class c=Student.class;
//再获取有参构造器对象
Constructor constructor=c.getDeclaredConstructor(String.class,int.class);
//通过有参构造器初始化对象返回
Student s=(Student)constructor.newInstance("yhh",12);
System.out.println(s);
System.out.println(s.getName());
System.out.println(s.getAge());
}
@Test
public void getDeclaredFields(){
//获取全部成员变量
Class c=Student.class;
Field[] fields=c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName()+"==>"+field.getType());
}
}
@Test
public void getDeclaredField() throws Exception {
//获取某个成员变量
Class c=Student.class;
Field field=c.getDeclaredField("age");
System.out.println(field.getName()+"==>"+field.getType());
}
@Test
public void setField() throws Exception {
//获取类名
Class c=Student.class;
//获取成员变量
Field nameF=c.getDeclaredField("name");
//获取无参构造器
Constructor constructor=c.getDeclaredConstructor();
//无视private
constructor.setAccessible(true);
//创建一个对象
Student s=(Student)constructor.newInstance();
//无视private
nameF.setAccessible(true);
// Student s=new Student();
//
nameF.set(s, "yhh");
System.out.println(s);
String value=nameF.get(s)+"";
System.out.println(value);
}
@Test
public void getDeclaredMethods(){
//得到所有Method对象
Class c=Student.class;
Method[] methods=c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName()+"==>"+method.getParameterCount()+"==>"+method.getReturnType());
}
}
@Test
public void getDeclaredMethod() throws Exception {
//得到所有对象
Class c=Student.class;
//定位toString方法利用方法名和参数
Method toString=c.getDeclaredMethod("toString");
System.out.println(toString.getName()+"==>"+toString.getParameterCount()+"==>"+toString.getReturnType());
Student student=new Student("yhh", 12);
//触发执行
//invoke(被触发方法对象,方法需要入参)
String value=(String)toString.invoke(student);
System.out.println(value);
}
用在类上、方法上、成员变量、构造器上对成分进行编译约束,标记的,有标记就进行特殊处理
1.标记@interface Book{} 2.方法重写约束 3.函数式接口约束@FunctionalInterface
特殊属性String value(); 单独使用时可以省略value名称不写
public class AnnotationDemo {
@Book(name = "java",authors = {"yhh","yh"})
public static void main(String[] args) {
}
}
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String name();
String[] authors();
String address() default "china";
}
用来注解自定义注解
@Target()约束标记范围
@Retention()约束存活范围
Annotation注解父类
AnnotatedElement
public class AnnotationDemo1 {
@Test
public void parseClass() {
//定义类对象
Class c=BookStore.class;
// Method method=c.getDeclaredMethod("run");
//判断这个类上是否使用了某个注解
if(c.isAnnotationPresent(Book.class)){
//获取注解对象
Book book=(Book) c.getDeclaredAnnotation(Book.class);
System.out.println(book.value());
System.out.println(book.price());
System.out.println(Arrays.toString(book.authors()));
}
}
}
@Book(value = "java",price = 99.5,authors = {"yhh","yh"})
class BookStore{
@Book(value = "c",price = 99.5,authors = {"yhh","yh"})
public void run(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String value();
double price() default 100;
String[] authors();
}
public class AnnotationDemo2 {
@MyTest
public void test01(){
System.out.println("======1=====");
}
public void test02(){
System.out.println("======2=====");
}
@MyTest
public void test03(){
System.out.println("======3=====");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
AnnotationDemo2 annotationDemo2=new AnnotationDemo2();
Class c=AnnotationDemo2.class;
Method[] methods=c.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(MyTest.class)){
method.invoke(annotationDemo2);
}
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTest{
}
数据交换(区分大小写)
用于系统配置文件
数据存储
yhh
22
select * from student where age < 18 && age > 12 ;
12 ;
]]>
DTD规范技术不能验证数据类型
Schema可以约束数据类型
DOM解析 面向对象解析
优点:生成DOM树可以随意访问修改删除 缺点:占内存较多
SAX解析 事件驱动解析
优点:读取一行解析一行并释放内存 缺点:使用过的元素不能访问,只能查找
1.对象通过工厂的方法创建和返回,可以为对象进行加工和数据注入
2.可以实现类与类之间的解耦
生产对象的方法,产生一个工厂类相当于中间分配结点
创建一个新类,包装原始类,从而在新类中提升原来类的功能
简化io流读写数据
//完成文件复制
IOUtils.copy(new FileInputStream(), new FileOutputStream());
//完成文件复制到文件夹
FileUtils.copyFileToDirectory();
//复制文件夹到文件夹
FileUtils.copyDirectoryToDirectory();
//java1.7以后
Files.copy(, );
,标记的,有标记就进行特殊处理
1.标记@interface Book{} 2.方法重写约束 3.函数式接口约束@FunctionalInterface
特殊属性String value(); 单独使用时可以省略value名称不写
public class AnnotationDemo {
@Book(name = "java",authors = {"yhh","yh"})
public static void main(String[] args) {
}
}
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String name();
String[] authors();
String address() default "china";
}
用来注解自定义注解
@Target()约束标记范围
@Retention()约束存活范围
Annotation注解父类
AnnotatedElement
public class AnnotationDemo1 {
@Test
public void parseClass() {
//定义类对象
Class c=BookStore.class;
// Method method=c.getDeclaredMethod("run");
//判断这个类上是否使用了某个注解
if(c.isAnnotationPresent(Book.class)){
//获取注解对象
Book book=(Book) c.getDeclaredAnnotation(Book.class);
System.out.println(book.value());
System.out.println(book.price());
System.out.println(Arrays.toString(book.authors()));
}
}
}
@Book(value = "java",price = 99.5,authors = {"yhh","yh"})
class BookStore{
@Book(value = "c",price = 99.5,authors = {"yhh","yh"})
public void run(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Book{
String value();
double price() default 100;
String[] authors();
}
public class AnnotationDemo2 {
@MyTest
public void test01(){
System.out.println("======1=====");
}
public void test02(){
System.out.println("======2=====");
}
@MyTest
public void test03(){
System.out.println("======3=====");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
AnnotationDemo2 annotationDemo2=new AnnotationDemo2();
Class c=AnnotationDemo2.class;
Method[] methods=c.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(MyTest.class)){
method.invoke(annotationDemo2);
}
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyTest{
}
数据交换(区分大小写)
用于系统配置文件
数据存储
yhh
22
select * from student where age < 18 && age > 12 ;
12 ;
]]>
DTD规范技术不能验证数据类型
Schema可以约束数据类型
DOM解析 面向对象解析
优点:生成DOM树可以随意访问修改删除 缺点:占内存较多
SAX解析 事件驱动解析
优点:读取一行解析一行并释放内存 缺点:使用过的元素不能访问,只能查找
1.对象通过工厂的方法创建和返回,可以为对象进行加工和数据注入
2.可以实现类与类之间的解耦
生产对象的方法,产生一个工厂类相当于中间分配结点
创建一个新类,包装原始类,从而在新类中提升原来类的功能
简化io流读写数据
//完成文件复制
IOUtils.copy(new FileInputStream(), new FileOutputStream());
//完成文件复制到文件夹
FileUtils.copyFileToDirectory();
//复制文件夹到文件夹
FileUtils.copyDirectoryToDirectory();
//java1.7以后
Files.copy(, );