Java高级
抽象类和抽象方法
1.定义
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。
类的设计应该保证父类和子类都能够共享特征。
有时候将一个父类设计的非常抽象,以至于他都没有具体的实例,这样的类叫做抽象类。
优势:不能被实例化
2.abstract修饰类:抽象类
抽象类不能实例化
抽象类中一定有构造器,便于子类实例化时调用(涉及:子类实例化的全过程)
开发中,都会提供抽象类的子类,让子类对象使用,完成相关操作。
3.abstract修饰方法:抽象方法
抽象方法只有方法的声明,没有方法体。
包含抽象方法的类,一定是一个抽象方法,然而,抽象类中可以没有抽象方法。
若子类重写类父类中的所有方法后,此子类方可实例化。
若子类没有重写父类中的所有方法抽象方法,
则此子类也是一个抽象类,需要使用abstract修饰该子类。
4.abstract关键字的注意事项
abstract不能用来修饰:属性、构造器等结构。
abstract不能用来修饰私有方法、静态方法、final修饰的方法。
接口
接口的特性:
属性:需要public static final修饰
方法:要求public abstract
没有构造方法,也没有程序块
接口不能创建对象,子类多实现接口来做事
接口也是一种引用数据类型
接口是完全抽象的。(抽象类是半抽象的)或者说,接口是特殊的抽象类。
接口和抽象类的相同点和不同点
可以实现多个接口,不能继承多个类
final关键字
final可以声明类、属性、方法
final标记的类不能被继承(final和abstract不能同时存在),没有子类
final标记的基本数据类型不能被改变//public void func(final int i){i++;}会报错
final标记的引用数据类型是可以改变其属性的(不改变引用数据类型的地址,不能new)//public void func(final Object o){o.i++;}
final标记的方法不能被重写,可以重载
final标记的标量是常量,一般public static final double Pi=3.14,常量可以被私有(goto 和 const在java中是关键字,但不过被使用,这种叫做保留关键字)
枚举
枚举指的是一组固定的常量组成的类型
类型安全:取值只能在涌现的范围内选择
public enum Season { Spring("春天","春意盎然"), Summer("夏天","夏日炎炎"), ; private String seasonName; private String seasonDesc; Season(String seasonName, String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } public String getSeasonName() { return seasonName; } public void setSeasonName(String seasonName) { this.seasonName = seasonName; } public String getSeasonDesc() { return seasonDesc; } public void setSeasonDesc(String seasonDesc) { this.seasonDesc = seasonDesc; } }
public class TestSeason { public static void main(String[] args) { Season spring = Season.Spring; System.out.println(spring.getSeasonName()+"---"+spring.getSeasonDesc()); } }
异常
谁调用,谁处理
异常处理的五个关键字
捕获异常:try/catch/finally
抛出异常:throw 可以手动抛出异常对象;例如throw new Exception(“异常信息”)
声明异常:throws 声明方法 可能要抛出的各种异常了,向上传递异常,直到Main函数 保证程序可以正常运行
returnType methodName(…) throws Exception{
throw new Exception(“异常信息”);
}
运行时异常RuntimeException
Exception———————————————————异常层次结构的根类
ArithmeticException——————————————–算术错误情形,如 以零作为除数
ArrayIndexOutOfExceptionBoundsException————数组下标越界
NullPointerException——————————————-尝试访问null对象成员
NumberFormatException————————————-数字格式转换异常,如 把”abc”转换成数字
检查异常CheckException:检查异常是程序员必须进行处理
何时需要自定义异常
当JDK中的异常不能满足程序需要的时候
自定义异常
public class MyException extends Exception{//自定义异常 private int errorCode;//异常编码 public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public MyException() { } public MyException(int errorCode,String msg) { super(msg); this.errorCode = errorCode; } }
public static void main(String[] args) { System.out.println("请输入1~3之间的任何一个数:"); Scanner input = new Scanner(System.in); try{ int num=input.nextInt(); if (num==1){ System.out.println("课程1"); }else if (num==2){ System.out.println("课程2"); }else if(num==3){ System.out.println("课程3"); }else { System.out.println("输入错误,输入的数不在1~3之间"); } }catch (Exception e){ System.out.println("输出错误,发生异常"); }finally { System.out.println("欢迎提出建议"); } }
public class Item07 { private int age; public void setAge(int age) throws MyException{ if (age<=100&&0<=age){ this.age=age; }else { throw new MyException(1001,"年龄必须在1到100岁之间"); } } public static void main(String[] args) { Item07 item07 = new Item07(); try { item07.setAge(101); } catch (MyException e) { System.out.println("异常编码:"+e.getErrorCode()+"异常信息:"+e.getMessage()); } } }
注解
内置的注解
Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用在代码的注解是
-
@Override – 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
-
@Deprecated – 标记过时方法。如果使用该方法,会报编译警告。
-
@SuppressWarnings – 指示编译器去忽略注解中声明的警告。
作用在其他注解的注解(或者说 元注解)是:
-
@Retention – 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
-
@Documented – 标记这些注解是否包含在用户文档中。
-
@Target – 标记这个注解应该是哪种 Java 成员。
-
@Inherited – 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
从 Java 7 开始,额外添加了 3 个注解:
-
@SafeVarargs – Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
-
@FunctionalInterface – Java 8 开始支持,标识一个匿名函数或函数式接口。
-
@Repeatable – Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
自定义注解
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { int age() default 20; }
import java.lang.annotation.Annotation; public class Person { @Deprecated private String name; @MyAnnotation(age = 16) private int age; public void sayHi(){ } @MyAnnotation(age = 16) public void setAge(){ } public void checkAge() throws NoSuchFieldException, NoSuchMethodException { //通过反射加载Person类,并获取名为"age"的属性下的所有注解 // Annotation[] annotations = Person.class.getDeclaredField("age").getAnnotations();//getField("age").getAnnotations(); Annotation[] annotations = Person.class.getMethod("setAge").getAnnotations(); //遍历输出 for (Annotation a : annotations) { if (a instanceof MyAnnotation){//找到自定义注解 if (((MyAnnotation)a).age()<18){//读取注解中的年龄信息,并进行判断 System.out.println("未成年"); }else { System.out.println("具备选举权"); } } } } public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException { Person person = new Person(); person.checkAge(); } }
内部类
内部类与外部类的关系
1.成员内部类的创建需要依赖于外部类对象(成员方法必须用过对象调用),在没有外部类实例之前无法创建成员内部类对象
2.内部类与外部类相对独立,不是is a关系
3.私有属性的相互访问,内部类可以直接访问外部类,而外部类访问内部类需要内部类的对象来访问
4.创建内部类的语法
在外部类内部创建内部类对象Inner inner = new Inner();
在外部类外部创建内部类对象,外部类.内部类 inner=new Outer().new Inner();
5.在内部类内部使用隐藏的外部类对象,外部类类名.this
内部类的优势
内部类不受外部类是否继承各类,是多重继承的完美解决方案,是对JAVA单一继承的有益补充
内部类的分类
静态内部类
使用static修饰,类比静态方法,不需要外部类对象产生就内使用
不能访问外部类的成员域,只能访问静态域
创建语法
1.外部类内部:与成员内部类一样
2.外部了外部:Inner inner=new Outer.Inner();
非静态内部类
对外部完全隐藏,因此方法内部类不能用任何的访问修饰符
方法内部类没有访问形参,这个形参是可以在方法中随意修改的,一旦方法内部类中使用了形参,这个形参必须被声明为final
匿名内部类
1.必须继承一个抽象类或者实现一个接口
2.没有构造方法
反射
在编译时不确定哪个类被加载,而在程序运行时才加载、探知、使用
基于Class类
Class类是Java反射机制的起源和入口,每个类都有自己的Class对象,用于获取与类相关的各种信息,提供了获取信息的相关方法,Class类继承自Object类
优点
提高了Java程序的灵活性和扩展性,降低了耦合性
问题
可读性较差,反射会模糊程序内部逻辑
主要使用到的类
Class类—可获取类与类的成员信息
Field类—可访问类的属性
Method类—可调用类的方法
Constructor类—可调用类的构造方法
使用反射机制的一般步骤
1.通过反射加载类(三种方式)
//第一种:对象名.getClass(); Student student = new Student("jack", 10); Class aClass=student.getClass(); //第二种:类名.class; Class aClass = Student.class; //第三种:Class.forName("加载类的所在路径") Class aClass = Class.forName("com.cx.demo.Student");
2.通过反射创建对象(两种方式)
Class aClass = Class.forName("com.cx.demo.Student"); //1.调用无参数的构造方法 Student student =(Student) aClass.newInstance();//创建一个实例 //2.调用指定构造方法getDeclaredFields(指定构造方法对应参数的数据类型) Constructor con = aClass.getDeclaredConstructor(String.class,int.class); Student ton = (Student)con.newInstance("ton", 23);//创建一个实例
3.通过反射操作属性
Class clazz = Class.forName("com.cx.demo.Student"); Student stu = (Student) clazz.newInstance();//属性是对象的一部分 //getDeclaredFields():所有属性,包括私有的 Field[] declaredFields = clazz.getDeclaredFields(); //getDeclaredField("属性名"):指定属性 Field name = clazz.getDeclaredField("name"); //stu.setName设置属性值 name.setAccessible(true);//使得可以获取私有属性 如果是private属性,必须设置为true name.set(stu,"张三");
4.通过反射动态执行方法
Class clazz = Class.forName("com.cx.demo.Student"); Student stu = (Student) clazz.newInstance(); //1.得到方法getDeclaredMethod("方法名",方法所带参数的数据类型) Method show = clazz.getDeclaredMethod("show", String.class); //2.动态调用方法invoke(所属对象,传入的参数) show.invoke(stu,"反射太麻烦了"); //所有的方法,不包括过构造方法 Method[] declaredMethods = aClass.getDeclaredMethods();
几个常用的工具类
时间转换类
SimpleDateFormat
使用方法
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TestDate { //"2022-10-18"-->Date public static void main(String[] args) { String str = "2022-10-18"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = sdf.parse(str);//String--->Date System.out.println(date); String format = sdf.format(date);//Date---->String System.out.println(format); } catch (ParseException e) { e.printStackTrace(); } } }
工具类案例
import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil { //日期格式 private static final String pattern="yyyy-MM-dd"; private static final SimpleDateFormat sdf=new SimpleDateFormat(pattern); //将字符串转换成日期 public static Date convertToDate(String str) throws Exception{ Date date=null; date=sdf.parse(str); return date; } //将日期转换字符串 public static String convertToString(Date date){ String str=null; str=sdf.format(date); return str; } }
日历
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class DateDemo { public static void main(String[] args) { Date now = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String dataStr = simpleDateFormat.format(now); System.out.println("今天的日期是"+dataStr); System.out.println("今天的日期是"+now); Calendar calendar=Calendar.getInstance(); System.out.println(calendar); System.out.println(calendar.getTime()); System.out.println(calendar.get(Calendar.YEAR)); System.out.println(calendar.get(Calendar.MONTH));//0是一月,少一个月 System.out.println(calendar.get(Calendar.DAY_OF_WEEK));//星期天是第一天 calendar.add(Calendar.MONTH,1); System.out.println("一个月后:"+calendar.getTime()); } }
import java.text.SimpleDateFormat; import java.util.Calendar; public class TestCalendar { public static void main(String[] args) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日"); Calendar calendar=Calendar.getInstance(); calendar.set(2012,4,6); System.out.println(simpleDateFormat.format(calendar.getTime())+"是一年中的第"+calendar.get(Calendar.WEEK_OF_YEAR)+"星期"); } }
字符串
public class item02 { public static void main(String[] args) { String str="hello"; String num="12345"; String str1= new String("good"); System.out.println(str.length());//长度
抽象类和抽象方法
1.定义
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。
类的设计应该保证父类和子类都能够共享特征。
有时候将一个父类设计的非常抽象,以至于他都没有具体的实例,这样的类叫做抽象类。
优势:不能被实例化
2.abstract修饰类:抽象类
抽象类不能实例化
抽象类中一定有构造器,便于子类实例化时调用(涉及:子类实例化的全过程)
开发中,都会提供抽象类的子类,让子类对象使用,完成相关操作。
3.abstract修饰方法:抽象方法
抽象方法只有方法的声明,没有方法体。
包含抽象方法的类,一定是一个抽象方法,然而,抽象类中可以没有抽象方法。
若子类重写类父类中的所有方法后,此子类方可实例化。
若子类没有重写父类中的所有方法抽象方法,
则此子类也是一个抽象类,需要使用abstract修饰该子类。
4.abstract关键字的注意事项
abstract不能用来修饰:属性、构造器等结构。
abstract不能用来修饰私有方法、静态方法、final修饰的方法。
接口
接口的特性:
属性:需要public static final修饰
方法:要求public abstract
没有构造方法,也没有程序块
接口不能创建对象,子类多实现接口来做事
接口也是一种引用数据类型
接口是完全抽象的。(抽象类是半抽象的)或者说,接口是特殊的抽象类。
接口和抽象类的相同点和不同点
可以实现多个接口,不能继承多个类
final关键字
final可以声明类、属性、方法
final标记的类不能被继承(final和abstract不能同时存在),没有子类
final标记的基本数据类型不能被改变//public void func(final int i){i++;}会报错
final标记的引用数据类型是可以改变其属性的(不改变引用数据类型的地址,不能new)//public void func(final Object o){o.i++;}
final标记的方法不能被重写,可以重载
final标记的标量是常量,一般public static final double Pi=3.14,常量可以被私有(goto 和 const在java中是关键字,但不过被使用,这种叫做保留关键字)
枚举
枚举指的是一组固定的常量组成的类型
类型安全:取值只能在涌现的范围内选择
public enum Season { Spring("春天","春意盎然"), Summer("夏天","夏日炎炎"), ; private String seasonName; private String seasonDesc; Season(String seasonName, String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } public String getSeasonName() { return seasonName; } public void setSeasonName(String seasonName) { this.seasonName = seasonName; } public String getSeasonDesc() { return seasonDesc; } public void setSeasonDesc(String seasonDesc) { this.seasonDesc = seasonDesc; } }
public class TestSeason { public static void main(String[] args) { Season spring = Season.Spring; System.out.println(spring.getSeasonName()+"---"+spring.getSeasonDesc()); } }
异常
谁调用,谁处理
异常处理的五个关键字
捕获异常:try/catch/finally
抛出异常:throw 可以手动抛出异常对象;例如throw new Exception(“异常信息”)
声明异常:throws 声明方法 可能要抛出的各种异常了,向上传递异常,直到Main函数 保证程序可以正常运行
returnType methodName(…) throws Exception{
throw new Exception(“异常信息”);
}
运行时异常RuntimeException
Exception———————————————————异常层次结构的根类
ArithmeticException——————————————–算术错误情形,如 以零作为除数
ArrayIndexOutOfExceptionBoundsException————数组下标越界
NullPointerException——————————————-尝试访问null对象成员
NumberFormatException————————————-数字格式转换异常,如 把”abc”转换成数字
检查异常CheckException:检查异常是程序员必须进行处理
何时需要自定义异常
当JDK中的异常不能满足程序需要的时候
自定义异常
public class MyException extends Exception{//自定义异常 private int errorCode;//异常编码 public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public MyException() { } public MyException(int errorCode,String msg) { super(msg); this.errorCode = errorCode; } }
public static void main(String[] args) { System.out.println("请输入1~3之间的任何一个数:"); Scanner input = new Scanner(System.in); try{ int num=input.nextInt(); if (num==1){ System.out.println("课程1"); }else if (num==2){ System.out.println("课程2"); }else if(num==3){ System.out.println("课程3"); }else { System.out.println("输入错误,输入的数不在1~3之间"); } }catch (Exception e){ System.out.println("输出错误,发生异常"); }finally { System.out.println("欢迎提出建议"); } }
public class Item07 { private int age; public void setAge(int age) throws MyException{ if (age<=100&&0<=age){ this.age=age; }else { throw new MyException(1001,"年龄必须在1到100岁之间"); } } public static void main(String[] args) { Item07 item07 = new Item07(); try { item07.setAge(101); } catch (MyException e) { System.out.println("异常编码:"+e.getErrorCode()+"异常信息:"+e.getMessage()); } } }
注解
内置的注解
Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用在代码的注解是
-
@Override – 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
-
@Deprecated – 标记过时方法。如果使用该方法,会报编译警告。
-
@SuppressWarnings – 指示编译器去忽略注解中声明的警告。
作用在其他注解的注解(或者说 元注解)是:
-
@Retention – 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
-
@Documented – 标记这些注解是否包含在用户文档中。
-
@Target – 标记这个注解应该是哪种 Java 成员。
-
@Inherited – 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
从 Java 7 开始,额外添加了 3 个注解:
-
@SafeVarargs – Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
-
@FunctionalInterface – Java 8 开始支持,标识一个匿名函数或函数式接口。
-
@Repeatable – Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
自定义注解
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { int age() default 20; }
import java.lang.annotation.Annotation; public class Person { @Deprecated private String name; @MyAnnotation(age = 16) private int age; public void sayHi(){ } @MyAnnotation(age = 16) public void setAge(){ } public void checkAge() throws NoSuchFieldException, NoSuchMethodException { //通过反射加载Person类,并获取名为"age"的属性下的所有注解 // Annotation[] annotations = Person.class.getDeclaredField("age").getAnnotations();//getField("age").getAnnotations(); Annotation[] annotations = Person.class.getMethod("setAge").getAnnotations(); //遍历输出 for (Annotation a : annotations) { if (a instanceof MyAnnotation){//找到自定义注解 if (((MyAnnotation)a).age()<18){//读取注解中的年龄信息,并进行判断 System.out.println("未成年"); }else { System.out.println("具备选举权"); } } } } public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException { Person person = new Person(); person.checkAge(); } }
内部类
内部类与外部类的关系
1.成员内部类的创建需要依赖于外部类对象(成员方法必须用过对象调用),在没有外部类实例之前无法创建成员内部类对象
2.内部类与外部类相对独立,不是is a关系
3.私有属性的相互访问,内部类可以直接访问外部类,而外部类访问内部类需要内部类的对象来访问
4.创建内部类的语法
在外部类内部创建内部类对象Inner inner = new Inner();
在外部类外部创建内部类对象,外部类.内部类 inner=new Outer().new Inner();
5.在内部类内部使用隐藏的外部类对象,外部类类名.this
内部类的优势
内部类不受外部类是否继承各类,是多重继承的完美解决方案,是对JAVA单一继承的有益补充
内部类的分类
静态内部类
使用static修饰,类比静态方法,不需要外部类对象产生就内使用
不能访问外部类的成员域,只能访问静态域
创建语法
1.外部类内部:与成员内部类一样
2.外部了外部:Inner inner=new Outer.Inner();
非静态内部类
对外部完全隐藏,因此方法内部类不能用任何的访问修饰符
方法内部类没有访问形参,这个形参是可以在方法中随意修改的,一旦方法内部类中使用了形参,这个形参必须被声明为final
匿名内部类
1.必须继承一个抽象类或者实现一个接口
2.没有构造方法
反射
在编译时不确定哪个类被加载,而在程序运行时才加载、探知、使用
基于Class类
Class类是Java反射机制的起源和入口,每个类都有自己的Class对象,用于获取与类相关的各种信息,提供了获取信息的相关方法,Class类继承自Object类
优点
提高了Java程序的灵活性和扩展性,降低了耦合性
问题
可读性较差,反射会模糊程序内部逻辑
主要使用到的类
Class类—可获取类与类的成员信息
Field类—可访问类的属性
Method类—可调用类的方法
Constructor类—可调用类的构造方法
使用反射机制的一般步骤
1.通过反射加载类(三种方式)
//第一种:对象名.getClass(); Student student = new Student("jack", 10); Class aClass=student.getClass(); //第二种:类名.class; Class aClass = Student.class; //第三种:Class.forName("加载类的所在路径") Class aClass = Class.forName("com.cx.demo.Student");
2.通过反射创建对象(两种方式)
Class aClass = Class.forName("com.cx.demo.Student"); //1.调用无参数的构造方法 Student student =(Student) aClass.newInstance();//创建一个实例 //2.调用指定构造方法getDeclaredFields(指定构造方法对应参数的数据类型) Constructor con = aClass.getDeclaredConstructor(String.class,int.class); Student ton = (Student)con.newInstance("ton", 23);//创建一个实例
3.通过反射操作属性
Class clazz = Class.forName("com.cx.demo.Student"); Student stu = (Student) clazz.newInstance();//属性是对象的一部分 //getDeclaredFields():所有属性,包括私有的 Field[] declaredFields = clazz.getDeclaredFields(); //getDeclaredField("属性名"):指定属性 Field name = clazz.getDeclaredField("name"); //stu.setName设置属性值 name.setAccessible(true);//使得可以获取私有属性 如果是private属性,必须设置为true name.set(stu,"张三");
4.通过反射动态执行方法
Class clazz = Class.forName("com.cx.demo.Student"); Student stu = (Student) clazz.newInstance(); //1.得到方法getDeclaredMethod("方法名",方法所带参数的数据类型) Method show = clazz.getDeclaredMethod("show", String.class); //2.动态调用方法invoke(所属对象,传入的参数) show.invoke(stu,"反射太麻烦了"); //所有的方法,不包括过构造方法 Method[] declaredMethods = aClass.getDeclaredMethods();
几个常用的工具类
时间转换类
SimpleDateFormat
使用方法
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TestDate { //"2022-10-18"-->Date public static void main(String[] args) { String str = "2022-10-18"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = sdf.parse(str);//String--->Date System.out.println(date); String format = sdf.format(date);//Date---->String System.out.println(format); } catch (ParseException e) { e.printStackTrace(); } } }
工具类案例
import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil { //日期格式 private static final String pattern="yyyy-MM-dd"; private static final SimpleDateFormat sdf=new SimpleDateFormat(pattern); //将字符串转换成日期 public static Date convertToDate(String str) throws Exception{ Date date=null; date=sdf.parse(str); return date; } //将日期转换字符串 public static String convertToString(Date date){ String str=null; str=sdf.format(date); return str; } }
日历
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class DateDemo { public static void main(String[] args) { Date now = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String dataStr = simpleDateFormat.format(now); System.out.println("今天的日期是"+dataStr); System.out.println("今天的日期是"+now); Calendar calendar=Calendar.getInstance(); System.out.println(calendar); System.out.println(calendar.getTime()); System.out.println(calendar.get(Calendar.YEAR)); System.out.println(calendar.get(Calendar.MONTH));//0是一月,少一个月 System.out.println(calendar.get(Calendar.DAY_OF_WEEK));//星期天是第一天 calendar.add(Calendar.MONTH,1); System.out.println("一个月后:"+calendar.getTime()); } }
import java.text.SimpleDateFormat; import java.util.Calendar; public class TestCalendar { public static void main(String[] args) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日"); Calendar calendar=Calendar.getInstance(); calendar.set(2012,4,6); System.out.println(simpleDateFormat.format(calendar.getTime())+"是一年中的第"+calendar.get(Calendar.WEEK_OF_YEAR)+"星期"); } }
字符串
public class item02 { public static void main(String[] args) { String str="hello"; String num="12345"; String str1= new String("good"); System.out.println(str.length());//长度 System.out.println(str.charAt(2));//取字符 System.out.println(str.indexOf("l"));//取字符下标 System.out.println(str.concat(str1));//拼接 System.out.println(str.substring(3, 5));//(] } }
import java.util.Scanner; public class Item05 { public static void main(String[] args) { char c; String str; Scanner scanner = new Scanner(System.in); System.out.println("请输入一个字符串"); str=scanner.next(); System.out.println("请输入要查找的字符"); c=scanner.next().charAt(0); if (str.indexOf(c)>-1){ int count=0; for (int i = 0; i < str.length(); i++) { if (c==(str.charAt(i))){ count++; } } System.out.println(str+"中包含"+count+"个"+c); }else { System.out.println(str+"中不存在"+c); } } }
public class Item06 { public static void main(String[] args) { String s = new String(); StringBuffer stringBuffer = new StringBuffer("1234556"); //千位分隔符 for (int i = stringBuffer.length() - 3; i > 0; i -= 3) { stringBuffer.insert(i, ","); } System.out.println(stringBuffer); } }
I/O流
操作文件
import java.io.File; import java.io.IOException; public class TestFile { public static void main(String[] args) { File dir=new File("/tmp/Temp/temp"); File file = new File(dir,"text.txt"); if (!dir.exists()){ dir.mkdir();//创建目录 } if (!file.exists()){//判断文件是否存在 try { file.createNewFile();//创建文件 } catch (IOException e) { e.printStackTrace(); } }else { System.out.println(file.getPath()); System.out.println(file.getName()); file.delete();//删除文件 dir.delete();//删除目录 } System.out.println(file.exists()); } }
使用FileInputStream读取文件
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class Main { public static void main(String[] args) { File dir = new File("/tmp/Temp/temp"); File file = new File("/tmp/Temp/temp/test.txt"); if (!dir.exists()) { dir.mkdir();//新建目录 } if (!file.exists()) { try { file.createNewFile();//新建文件 } catch (IOException e) { e.printStackTrace(); } } //读取文件 try { FileInputStream fileInputStream = new FileInputStream(file); int num = fileInputStream.read();//一次读取一个字节 System.out.println(num); int contentLength; byte[] bytes= new byte[1024]; String content=null; //超过1kb while ((contentLength = fileInputStream.read(bytes))!=-1){ content=new String(bytes,0,contentLength);//转化成字符串 } System.out.println(content); fileInputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
使用FileOutputStream写文件
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; public class FileWriteDemo { public static void main(String[] args) { try { FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Temp/temp/good.txt"); String msg="weekend"; byte[] bytes=msg.getBytes(StandardCharsets.UTF_8); fileOutputStream.write(bytes,0,bytes.length);//写文件 fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
使用BufferedReader和FileReader读取文件
import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class BufferReaderDemo { public static void main(String[] args) { try { BufferedReader bufferedReader = new BufferedReader(new FileReader("/tmp/Temp/temp/test.txt")); // int read = bufferedReader.read();//再次读取有可能丢失首字母 // System.out.println(read); //按行读取 // String readLine = null; // while ((readLine = bufferedReader.readLine()) != null) { // System.out.println(readLine); // } //读取十个字符 // char[] chars = new char[10]; // int length = bufferedReader.read(chars, 0, chars.length); // System.out.println(length); // System.out.println(new String(chars,0,length)); //超过十个字符 // char[] chars = new char[10]; // int length=0; // while ((length=bufferedReader.read(chars,0,chars.length))!=-1){ // System.out.println(new String(chars,0,length)); // } bufferedReader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
使用BufferedWriter和FileWriter写文件
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class BufferWriterDemo { public static void main(String[] args) { try { BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("/tmp/Temp/temp/new.txt")); bufferedWriter.write("first line"); bufferedWriter.newLine();//换行 bufferedWriter.write("second line"); bufferedWriter.newLine(); bufferedWriter.flush();//清楚空余 bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }
序列化与反序列化
import java.io.*; public class ObjectDemo { public static void main(String[] args) { // Student student = new Student("jack",20); try { //对象的序列化 // FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Temp/temp/student.bin"); // ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); // // objectOutputStream.writeObject(student); // objectOutputStream.close(); // fileOutputStream.close(); //反序列化 FileInputStream fileInputStream = new FileInputStream("/tmp/Temp/temp/student.bin"); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); Student student = (Student) objectInputStream.readObject(); System.out.println(student); fileInputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
泛型
public interface Person<T> { T getName(); void setName(T t); }
public class Student<T> implements Person{ private T t; public Student() { } public Student(T t) { this.setName(t); } public void show(T t){ System.out.println(t.getClass().getName()); System.out.println(t); } public T getT() { return t; } public void setT(T t) { this.t = t; } @Override public T getName() { return this.t; } @Override public void setName(Object o) { this.t= (T) o; } public static void main(String[] args) { // Student<String> student=new Student<>(); // student.show("jack"); Student<String> student = new Student<>("张三"); System.out.println(student.getName()); System.out.println(student.getT().getClass().getName()); } }
多线程
进程:系统运行的基本单位,有独立的内存空间和系统资源
线程:进程中执行运算的最小单位,处理机分配给线程,即真正在处理机上运行的是线程
线程的创建的两种方式
继承java.lang.thread类
实现java.lang.Runnable接口(还是要借助于thread启动)
1.定义线程
2.创建线程对象
3.启动线程
4.终止线程(不推荐手动终止)
cpu会随机执行里面的线程:主线程,自定义线程
线程的声明周期包括四个状态:新生状态,可运行状态,阻塞状态和死亡状态
多个线程处于可运行的状态(线程调度)
分配优先级 1的优先级最高,默认值是5,Thread.currentThread().getPriority()
更改优先级 new Thread().setPriority(4)
new Thread().join()添加进阻塞进程
Thread.sleep(500)当前线程停止执行,进入不可运行状态(阻塞),其他等待运行的进程机会是相等的
yield当前线程转入暂停运行的状态(不阻塞),如果没有其他等待执行的线程,当前线程会马上恢复执行,会优先级相同的或更高的执行
线程同步
关键字synchronized
同步方法
同步代码块
线程通信
wait()挂起当前线程,并释放共享资源的锁
notify()在因调用该对象的wait方法二阻塞的线程中随机选择一个解除阻塞,但要等到获得锁后才可以正真执行
notifyall将因调用该对象的wait方法而阻塞的所有线程一次性全部解除阻塞
这三个方法只能在同步方法或者同步代码块中使用
线程创建
//1.定义线程:通过继承的方式 public class MyThread extends Thread{ //重写run @Override public void run() { for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); } } public static void main(String[] args) { //cpu会随机执行里面的线程:主线程,自定义线程 //2.创建线程对象 MyThread myThread = new MyThread(); //3.启动线程 myThread.setName("我的线程");//定义线程名 myThread.start(); //主线程 for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); } } }
public class MyRun implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { // MyRun myRun = new MyRun(); // new Thread(myRun,"自定义线程名").start();//Thread才是真正的线程 // // //主线程 // for (int i = 0; i < 5; i++) { // //当前运行的是哪个线程 // System.out.println(Thread.currentThread().getName()+":"+i); // } //优先级只是cpu执行该线程的一个重要参考要素之一 MyRun myRun = new MyRun(); Thread t1 = new Thread(myRun, "线程1"); Thread t2 = new Thread(myRun, "线程2"); t1.setPriority(4); t2.setPriority(6); t1.start(); // t2.start(); for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); Thread.sleep(500); } } }
分苹果
public class ShareApple implements Runnable { private int count = 5;//苹果的总数 private boolean flag = true;//标记位,是否可以拿苹果 //拿苹果的方法 //同步方法 public synchronized boolean getApple() { // synchronized (this) {//同步代码块 if (count == 0)//是否有苹果 return false; count--; try { Thread.sleep(800); } catch (InterruptedException e) { e.printStackTrace(); } if (count >= 0) { System.out.println(Thread.currentThread().getName() + "成功拿到了一个苹果,还剩" + count + "个苹果"); } else { System.out.println(Thread.currentThread().getName() + "没有拿到苹果"); } return true; // } } @Override public void run() { while (flag) flag = getApple(); if (count == 0) { System.out.println(Thread.currentThread().getName() + "线程结束"); } } }
public class TestApple { public static void main(String[] args) { ShareApple shareApple = new ShareApple(); new Thread(shareApple,"小明").start(); new Thread(shareApple,"小黑").start(); } }
存取款
public class Account { private int balance = 500; public int getBalance() { return balance; } public void qu(int atm) { balance -= atm; } }
public class TestAccount implements Runnable { private Account account = new Account(); @Override public void run() { for (int i = 0; i < 4; i++) { makeWithDraw(100); if (account.getBalance() < 0) System.out.println("账户透支"); } } private void makeWithDraw(int atm) { synchronized (account) { if (account.getBalance() >= atm) { System.out.println(Thread.currentThread().getName() + "\t准备取款!"); account.qu(atm); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"\t完成取款"); }else { System.out.println("余额不足以支付\t"+Thread.currentThread().getName()+"\t取款的余额为"+account.getBalance()); } } } public static void main(String[] args) { TestAccount testAccount = new TestAccount(); Thread p1 = new Thread(testAccount, "张三"); Thread p2 = new Thread(testAccount, "张三的妻子"); p1.start(); p2.start(); } }
生产者消费者模式
public class Consumer extends Thread {//消费者 private ShareData data; Consumer(ShareData data) { this.data = data; } @Override public void run() { char s; do { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } s = data.getChar(); } while (s != 'D'); } }
public class Producer extends Thread { private ShareData data; Producer(ShareData data) { this.data = data; } @Override public void run() { //专门生产 for (char i = 'A'; i <= 'D'; i++) { data.produce(i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }
public class ShareData { private char c; private boolean flag = false;//信号量 //生产资源 public synchronized void produce(char c) { while (flag) { try { System.out.println("生产资源:消费者还没有消费,需要等待消费者进行消费"); wait();//线程立即挂起,释放锁和cpu资源 } catch (InterruptedException e) { e.printStackTrace(); } } flag = true; notify(); this.c = c; System.out.println("生产资源:生产者已经生产了产品" + c + ",等待消费者消费"); } //消费资源 public synchronized char getChar() { while (!flag) { try { System.out.println("消费资源:生产者还没有生产,无法消费消费。。。"); wait();//线程立即挂起,释放锁和cpu资源 } catch (InterruptedException e) { e.printStackTrace(); } } flag = false; notify(); System.out.println("消费资源:消费者消费了产品" + c + "通知生产者生产"); return c; } }
public class TestConsumer { public static void main(String[] args) { ShareData data = new ShareData(); new Producer(data).start(); new Consumer(data).start(); //定义了两个线程:每一次 都来争夺cpu资源 } }
死锁
public class DeadLockRunnable implements Runnable { //编号 public int num; //资源 private static Object chopsticks1 = new Object(); private static Object chopsticks2 = new Object(); private boolean flag =false;//信号量 /** * num = 1 拿到chopsticks1 等待chopsticks2 * num = 2 拿到chopsticks2 等待chopsticks1 */ @Override public void run() { if (num==1){ System.out.println(Thread.currentThread().getName()+"拿到了chopsticks1,等待chopsticks2"); synchronized (chopsticks1){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (chopsticks2){ System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } else if (num==2){ System.out.println(Thread.currentThread().getName()+"拿到了chopsticks2,等待chopsticks1"); synchronized (chopsticks2){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (chopsticks1){ System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } } }
public class DeadLockTest { public static void main(String[] args) { DeadLockRunnable deadLockRunnable1 = new DeadLockRunnable(); deadLockRunnable1.num=1; DeadLockRunnable deadLockRunnable2 = new DeadLockRunnable(); deadLockRunnable2.num=2; new Thread(deadLockRunnable1,"张三").start(); new Thread(deadLockRunnable2,"李四").start(); } }
线程通信
客户端与服务端
InetAddress类 无构造方法 getLocalHost获取本地ip getByName获取网络主机名
基于tcp:Socket(客户端)和Server Socket(服务器端)
ServerSocket.accept():获取客户端socket
Socket通信模型
进行网络通信是,Socket需要借助数据流来完成数据的传递工作
Socket类
两个Socket类的构造方法及其含义
Socket socket=new Socker(“localhost”,8800)
ServerSocket serverSocket = new ServerSocket(9000);
socket.getOutputStream();
os.write
1.建立连接
2.打开Socket关联的输入输出流
3.数据流中读写信息
4.关闭所有的数据流和Socket
ServerSocket类的accept()方法有何用处:获取客户端socket
import java.io.IOException; import java.io.InputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; public class Client { public static void main(String[] args) throws IOException {//客户端 //创建Socket Socket socket = new Socket(InetAddress.getLocalHost(),9000); //得到输出流 OutputStream os = socket.getOutputStream(); //写入字符串 // String msg="你好,服务器端,这是用户登录信息"; // os.write(msg.getBytes(StandardCharsets.UTF_8)); //写入对象 ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); User user = new User("Jack","123"); objectOutputStream.writeObject(user); //告诉服务器,消息发完了 socket.shutdownOutput(); //得到输入流 InputStream is = socket.getInputStream(); //读取信息 byte[] by = new byte[1024]; int len ;//= is.read(by); String content=null; //超过1kb while ((len=is.read(by))!=-1){ content=new String(by,0,len); } System.out.println("客户端发送的信息是:"+content); //告诉服务器,消息发完了 // socket.shutdownOutput(); //关闭 is.close(); os.close(); socket.close(); } }
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class MyServer { public static void main(String[] args) throws IOException, ClassNotFoundException { //1.创建的是ServerSocket,指定对应的端口号 System.out.println("服务器请求链接"); ServerSocket serverSocket = new ServerSocket(9000); //2.等待链接 Socket socket = serverSocket.accept(); System.out.println("服务器等待链接"); //3.得到输入流,其实就是客户端的输出流 InputStream is = socket.getInputStream(); //4.1读取字符串信息 // byte[] by = new byte[1024]; // int len;//= is.read(by); // String content = null; // //超过1kb // while ((len = is.read(by)) != -1) { // content = new String(by, 0, len); // } // System.out.println("客户端发送的信息是:" + content); //4.2读取对象 ObjectInputStream ois = new ObjectInputStream(is); User user = (User) ois.readObject(); String msg2=null; if ("123".equals(user.getPassword())){ msg2="欢迎你"+user.getUsername(); }else { msg2="用户名或密码错误"; } System.out.println(msg2); //得到输出流,对客户端进行响应 OutputStream os = socket.getOutputStream(); String msg = "你好,客户端,信息已经收到"; //writer os.write(msg.getBytes(StandardCharsets.UTF_8)); //5.关闭资源 is.close(); os.close(); socket.close(); serverSocket.close(); } }
import java.io.Serializable; public class User implements Serializable { private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
服务器端与多客户端
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class LoginServer {//多线程处理客户端 public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9000); Socket socket; System.out.println("服务器等待请求。。。。"); while (true) {//实现一直监听 socket = serverSocket.accept(); System.out.println("服务器接收到请求"); //多线程 LoginThread thread = new LoginThread(socket); thread.start(); } } }
import java.io.*; import java.net.InetAddress; import java.net.Socket; public class LoginClient1 { public static void main(String[] args) throws IOException { User user = new User("张三", "123"); Socket socket = new Socket(InetAddress.getLocalHost(), 9000); OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); ObjectInputStream ois = new ObjectInputStream(is); System.out.println("我是客户端1,给服务器发送登录信息。。。"); oos.writeObject(user); //告诉服务已经发送完了消息 socket.shutdownOutput(); //接收服务器的信息 byte[] temp = new byte[1024]; int len = is.read(temp); System.out.println("服务器的响应"+new String(temp,0,len)); socket.close(); } }
import java.io.*; import java.net.InetAddress; import java.net.Socket; public class LoginClient2 { public static void main(String[] args) throws IOException { User user = new User("李四", "123"); Socket socket = new Socket(InetAddress.getLocalHost(), 9000); OutputStream os = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); InputStream is = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(is); System.out.println("我是客户端2,给服务器发送信息"); oos.writeObject(user); //告诉服务已经发送完了消息 socket.shutdownOutput(); //接收服务器的信息 byte[] temp = new byte[1024]; int len = is.read(temp); System.out.println("服务器的响应"+new String(temp,0,len)); socket.close(); } }
import java.io.*; import java.net.Socket; import java.nio.charset.StandardCharsets; public class LoginThread extends Thread { private Socket socket; public LoginThread(Socket socket) { this.socket = socket; } @Override public void run() { //处理客户端请求 try (//写在小括号里会自动关闭资源close InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); ObjectInputStream ois = new ObjectInputStream(is); ) { //得到客户端的信息 User user = (User) ois.readObject(); //给客户端回信息 String msg = null; if (user == null) { msg = "没有发送登录信息,登录失败"; } else { msg = "欢迎你" + user.getUsername(); } System.out.println(msg); os.write(msg.getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
网络编程
ip地址与主机名
C类地址(192.0.0.0-223.255.255.0):192.168.0.0~192.168.255.255
InetAddress类 无构造方法 getLocalHost获取本地ip getByName获取网络主机名
基于tcp:Socket(客户端)和Server Socket(服务器端)
ServerSocket.accept():获取客户端socket
Socket通信模型
进行网络通信是,Socket需要借助数据流来完成数据的传递工作
Socket类
两个Socket类的构造方法及其含义
Socket socket=new Socker(“localhost”,8800)
ServerSocket serverSocket = new ServerSocket(9000);
socket.getOutputStream();
os.write
1.建立连接
2.打开Socket关联的输入输出流
3.数据流中读写信息
4.关闭所有的数据流和Socket
ServerSocket类的accept()方法有何用处:获取客户端socket
import java.net.InetAddress; import java.net.UnknownHostException; public class TestAddress { public static void main(String[] args) throws UnknownHostException { //InetAddress:IP地址包装类 InetAddress localHost = InetAddress.getLocalHost(); System.out.println(localHost.getHostAddress());//ip地址 System.out.println(localHost.getHostName());//主机名 //得到网络主机名 InetAddress address = InetAddress.getByName("www.baidu.com"); System.out.println(address.getHostAddress()); System.out.println(address.getHostName()); } }
UDP
基于UDP协议的Socket编程
1.利用DatagramSocket发送数据包
2.利用DatagramPacket对象封装数据包
3.利用DataGramPacket处理数据包
4.利用DataGramPacket接收数据包
建立发送端,接收端
创建数据
建立数据包
调用Socket的发送接收方法
关闭SOcket
发送端与接收端是两个独立运行的程序
import java.io.IOException; import java.net.*; import java.nio.charset.StandardCharsets; public class UDPSend {//发送端 public static void main(String[] args) throws IOException { DatagramSocket ds = new DatagramSocket(); byte[] msg = "最新的邮件来了。。。。".getBytes(StandardCharsets.UTF_8); //创建数据包,即将发送出去的数据包,发送的内容,收获的ip,端口号, DatagramPacket dp = new DatagramPacket(msg, 0, msg.length, InetAddress.getByName("localhost"), 9000); //发送数据 ds.send(dp); //关闭资源:socket ds.close(); } }
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class UDPReceive { public static void main(String[] args) throws IOException {//接收端 //1.创建DatagramSocket DatagramSocket ds = new DatagramSocket(9000); //2.创建Packet byte[] temp = new byte[1024]; DatagramPacket dp = new DatagramPacket(temp, temp.length); //3.接收数据 ds.receive(dp); //发送方的主机名 String hostName = dp.getAddress().getHostName(); //发送方的端口号 int port = dp.getPort(); System.out.println("发送方的主机名是"+hostName+"发送方的端口号是"+port); byte[] bytes = dp.getData();//获取接收到的内容 String msg=new String(bytes,0, dp.getLength()); System.out.println("发送过来的信息是:"+msg); //4.关闭资源 ds.close(); } }
DOM文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE students SYSTEM "student.dtd"> <students> <student id="1"> <name>王同</name> <class>java</class> <score>89</score> </student> <student id="2"> <name>李佳</name> <class>sql</class> <score>58</score> </student> <student id="3"> <name>李白</name> <class>python</class> <score>90</score> </student> </students>
<!ELEMENT students (student+)> <!ELEMENT student (name,class,score)> <!ATTLIST student id CDATA #IMPLIED> <!ELEMENT name (#PCDATA)> <!ELEMENT class (#PCDATA)> <!ELEMENT score (#PCDATA)>
public class TestXML { public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException { //1.得到document DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); //2.解析和加载xml文件到内存中去 Document document = documentBuilder.parse("student.xml"); //3.返回文档中的所有子节点 NodeList nodeList = document.getChildNodes(); Node root = nodeList.item(nodeList.getLength() - 1); System.out.println("root:" + root.getNodeName());//students //4.再查找他的子节点 NodeList childNodes = root.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node item = childNodes.item(i); if ("student".equals(item.getNodeName())) { NodeList nodes = item.getChildNodes(); for (int j = 0; j < nodes.getLength(); j++) { Node node = nodes.item(j); if ("name".equals(node.getNodeName())) { System.out.println("name:" + node.getTextContent()); } else if ("class".equals(node.getNodeName())) { System.out.println("class:" + node.getTextContent()); } else if ("score".equals(node.getNodeName())) { System.out.println("score:" + node.getTextContent()); } } } } } }
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.FileOutputStream; import java.io.IOException; public class UpdateXML { public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException { //使用DOM对XML文件进行数据修改 //1.得到document DocumentBuilderFactory dbf; dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); //解析和加载xml文件到内存中去 Document document = documentBuilder.parse("student.xml"); //1.删除某个节点 // NodeList list = document.getElementsByTagName("student"); // for (int i = 0; i < list.getLength(); i++) { // Element item = (Element)list.item(i); // //node:节点(文本节点),element:元素 // //凡是元素都是节点,但是节点不一定都是元素,例如:一个单纯的回车也是节点 //// System.out.println(item.getAttribute("id")); // if ("2".equals(item.getAttribute("id"))){ // item.getParentNode().removeChild(item); // } // } //2.添加节点 // //student(name class score) // Element student = document.createElement("student"); // student.setAttribute("id", "3");//设置属性值 // //name // Element stuName = document.createElement("name");//创建节点 // stuName.setTextContent("李白");//设置节点内容 // student.appendChild(stuName);//添加节点 // //class // Element stuClass = document.createElement("class"); // stuClass.setTextContent("python"); // student.appendChild(stuClass); // //score // Element stuScore = document.createElement("score"); // stuScore.setTextContent("90"); // student.appendChild(stuScore); // //找到根节点students // NodeList nodeList = document.getElementsByTagName("students"); // Node students = nodeList.item(nodeList.getLength() - 1); // students.appendChild(student); //修改:李白-》李清照 //1.查找节点 NodeList student3 = document.getElementsByTagName("student"); for (int i = 0; i < student3.getLength(); i++) { Element item = (Element)student3.item(i); if ("3".equals(item.getAttribute("id"))){ Node name = item.getElementsByTagName("name").item(0); //2.修改节点内容 name.setTextContent("李清照"); break; } } //保存成XML文件 TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource domSource = new DOMSource(document); // 设置编码类型 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); StreamResult result = new StreamResult(new FileOutputStream("student.xml")); // 把DOM树转换为XML文件 transformer.transform(domSource, result); } }
DOM4j
<?xml version="1.0" encoding="UTF-8"?> <books> <book id="book1"> <name>三国演义</name> <price>99.88</price> </book> <book id="book2"> <name>西游记</name> <price>77.88</price> </book> <book id="book3"> <name>李白的诗</name> <price>88.88</price> </book> </books>
import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.util.Iterator; import java.util.List; public class TestDom01 { public static void main(String[] args) throws DocumentException { SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); System.out.println(root.getName());//root //遍历显示所有的数据 List<Element> list = root.elements("book"); for (Element book:list){ Attribute id = book.attribute("id"); System.out.println("id:"+id.getValue()); //迭代器 Iterator<Element> it = book.elementIterator(); while (it.hasNext()){ Element element = it.next(); System.out.println(element.getName()+":"+element.getText()); } System.out.println("----------------"); } } }
import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import java.io.FileWriter; import java.io.IOException; import java.util.List; public class TestDom02 { public static void main(String[] args) throws DocumentException, IOException { //需求:实现 删除 id="book3"这样的一个节点 /* <book id="book"> <name>李白的诗</name> <price>88.88</price> </book> */ //解析xml文件 SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); //找到相应的节点 List<Element> bookList = root.elements("book"); for (Element book:bookList){ Attribute id = book.attribute("id"); if ("book3".equals(id.getValue())){ book.getParent().remove(book);//删除 } } //保存到xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileWriter("books.xml")); writer.write(doc); writer.close(); System.out.println("删除成功"); } }
import org.dom4j.*; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import java.io.FileWriter; import java.io.IOException; import java.util.List; public class TestDom03 { public static void main(String[] args) throws DocumentException, IOException { //需求:实现 新增节点 /* <book id="book"> <name>李白的诗</name> <price>88.88</price> </book> */ //解析xml文件 SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); //新增节点 Element book = DocumentHelper.createElement("book"); book.addAttribute("id", "book3"); Element name = DocumentHelper.createElement("name");//创建节点 name.setText("李白的诗");//设置属性 book.add(name);//添加节点 Element price = DocumentHelper.createElement("price"); price.setText("88.88"); book.add(price); root.add(book); //保存到xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileWriter("books.xml")); writer.write(doc); writer.close(); System.out.println("新增成功"); } }
import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Iterator; import java.util.List; public class TestDom04 { public static void main(String[] args) throws DocumentException, IOException { //需求 实现 修改 id="book3"这样的一个节点 李白的诗-》李清照的诗句2.外部类外部:StaticInnerClass.Inner inne SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); System.out.println(root.getName());//root //遍历所有的数据 List<Element> list = root.elements("book"); for (Element book : list) { //找到对应的节点 if ("book3".equals(book.attribute("id").getValue())) { //迭代器 Iterator<Element> it = book.elementIterator(); while (it.hasNext()) { Element element = it.next(); //找到要修改的文本 if ("李白的诗".equals(element.getText())) { element.setText("李清照的诗"); System.out.println(element.getName() + ":" + element.getText()); break; } } break; } } //保存到xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileWriter("books.xml")); writer.write(doc); writer.close(); System.out.println("修改成功"); } }
集合
2.外部类外部:StaticInnerClass.Inner inne
import java.util.HashSet; import java.util.Set; public class Worker { private String name;//姓名 private int age;//年龄 private int salary;//收入 public Worker(String name, int age, int salary) { this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return "Worker{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } @Override public int hashCode() { // TODO Auto-generated method stub return this.name.hashCode() + age + salary; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (this.getClass() != obj.getClass()) { return false; } Worker obj2 = (Worker) obj; if (this.name.equals(obj2.name) && this.age == obj2.age && this.salary == obj2.salary) { return true; } return false; } public static void main(String[] args) { Set<Worker> hashSet = new HashSet<>(); //hashcode作为索引或者说是唯一标识 hashSet.add(new Worker("zhang3", 18, 1500)); hashSet.add(new Worker("li4", 18, 1500)); hashSet.add(new Worker("wang5", 18, 1600)); hashSet.add(new Worker("zhao6", 18, 2000)); hashSet.add(new Worker("zhao6", 18, 2000)); for (Worker worker : hashSet) { System.out.println(worker); } } }
import java.util.HashSet; import java.util.Set; import java.util.TreeSet; public class Worker implements Comparable { private String name;//姓名 private int age;//年龄 private int salary;//收入 public Worker(String name, int age, int salary) { this.name = name; this.age = age; this.salary = salary; } 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 int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } @Override public String toString() { return "Worker{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } @Override public int compareTo(Object o) { if (this == o) { return 0; } else { if (o instanceof Worker) { Worker worker = (Worker) o; if (this.age != worker.getAge()) { return this.age - worker.getAge(); } else if (this.salary != worker.getSalary()) { return this.salary-worker.getSalary(); } else { return this.name.compareTo(worker.getName()); } } else { try { throw new Exception("只能比较Worker对象"); } catch (Exception e) { e.printStackTrace(); } } } return 0; } public static void main(String[] args) { TreeSet<Worker> set = new TreeSet<>(); set.add(new Worker("zhang3", 18, 1500)); set.add(new Worker("li4", 18, 1500)); set.add(new Worker("wang5", 18, 1600)); set.add(new Worker("zhao6", 17, 2000)); for (Worker worker : set) { System.out.print(worker.getName()+"\t"); } } }
System.out.println(str.charAt(2));//取字符 System.out.println(str.indexOf("l"));//取字符下标 System.out.println(str.concat(str1));//拼接 System.out.println(str.substring(3, 5));//(] } }
import java.util.Scanner; public class Item05 { public static void main(String[] args) { char c; String str; Scanner scanner = new Scanner(System.in); System.out.println("请输入一个字符串"); str=scanner.next(); System.out.println("请输入要查找的字符"); c=scanner.next().charAt(0); if (str.indexOf(c)>-1){ int count=0; for (int i = 0; i < str.length(); i++) { if (c==(str.charAt(i))){ count++; } } System.out.println(str+"中包含"+count+"个"+c); }else { System.out.println(str+"中不存在"+c); } } }
public class Item06 { public static void main(String[] args) { String s = new String(); StringBuffer stringBuffer = new StringBuffer("1234556"); //千位分隔符 for (int i = stringBuffer.length() - 3; i > 0; i -= 3) { stringBuffer.insert(i, ","); } System.out.println(stringBuffer); } }
I/O流
操作文件
import java.io.File; import java.io.IOException; public class TestFile { public static void main(String[] args) { File dir=new File("/tmp/Temp/temp"); File file = new File(dir,"text.txt"); if (!dir.exists()){ dir.mkdir();//创建目录 } if (!file.exists()){//判断文件是否存在 try { file.createNewFile();//创建文件 } catch (IOException e) { e.printStackTrace(); } }else { System.out.println(file.getPath()); System.out.println(file.getName()); file.delete();//删除文件 dir.delete();//删除目录 } System.out.println(file.exists()); } }
使用FileInputStream读取文件
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class Main { public static void main(String[] args) { File dir = new File("/tmp/Temp/temp"); File file = new File("/tmp/Temp/temp/test.txt"); if (!dir.exists()) { dir.mkdir();//新建目录 } if (!file.exists()) { try { file.createNewFile();//新建文件 } catch (IOException e) { e.printStackTrace(); } } //读取文件 try { FileInputStream fileInputStream = new FileInputStream(file); int num = fileInputStream.read();//一次读取一个字节 System.out.println(num); int contentLength; byte[] bytes= new byte[1024]; String content=null; //超过1kb while ((contentLength = fileInputStream.read(bytes))!=-1){ content=new String(bytes,0,contentLength);//转化成字符串 } System.out.println(content); fileInputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
使用FileOutputStream写文件
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; public class FileWriteDemo { public static void main(String[] args) { try { FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Temp/temp/good.txt"); String msg="weekend"; byte[] bytes=msg.getBytes(StandardCharsets.UTF_8); fileOutputStream.write(bytes,0,bytes.length);//写文件 fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
使用BufferedReader和FileReader读取文件
import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class BufferReaderDemo { public static void main(String[] args) { try { BufferedReader bufferedReader = new BufferedReader(new FileReader("/tmp/Temp/temp/test.txt")); // int read = bufferedReader.read();//再次读取有可能丢失首字母 // System.out.println(read); //按行读取 // String readLine = null; // while ((readLine = bufferedReader.readLine()) != null) { // System.out.println(readLine); // } //读取十个字符 // char[] chars = new char[10]; // int length = bufferedReader.read(chars, 0, chars.length); // System.out.println(length); // System.out.println(new String(chars,0,length)); //超过十个字符 // char[] chars = new char[10]; // int length=0; // while ((length=bufferedReader.read(chars,0,chars.length))!=-1){ // System.out.println(new String(chars,0,length)); // } bufferedReader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
使用BufferedWriter和FileWriter写文件
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class BufferWriterDemo { public static void main(String[] args) { try { BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("/tmp/Temp/temp/new.txt")); bufferedWriter.write("first line"); bufferedWriter.newLine();//换行 bufferedWriter.write("second line"); bufferedWriter.newLine(); bufferedWriter.flush();//清楚空余 bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }
序列化与反序列化
import java.io.*; public class ObjectDemo { public static void main(String[] args) { // Student student = new Student("jack",20); try { //对象的序列化 // FileOutputStream fileOutputStream = new FileOutputStream("/tmp/Temp/temp/student.bin"); // ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); // // objectOutputStream.writeObject(student); // objectOutputStream.close(); // fileOutputStream.close(); //反序列化 FileInputStream fileInputStream = new FileInputStream("/tmp/Temp/temp/student.bin"); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); Student student = (Student) objectInputStream.readObject(); System.out.println(student); fileInputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
泛型
public interface Person<T> { T getName(); void setName(T t); }
public class Student<T> implements Person{ private T t; public Student() { } public Student(T t) { this.setName(t); } public void show(T t){ System.out.println(t.getClass().getName()); System.out.println(t); } public T getT() { return t; } public void setT(T t) { this.t = t; } @Override public T getName() { return this.t; } @Override public void setName(Object o) { this.t= (T) o; } public static void main(String[] args) { // Student<String> student=new Student<>(); // student.show("jack"); Student<String> student = new Student<>("张三"); System.out.println(student.getName()); System.out.println(student.getT().getClass().getName()); } }
多线程
进程:系统运行的基本单位,有独立的内存空间和系统资源
线程:进程中执行运算的最小单位,处理机分配给线程,即真正在处理机上运行的是线程
线程的创建的两种方式
继承java.lang.thread类
实现java.lang.Runnable接口(还是要借助于thread启动)
1.定义线程
2.创建线程对象
3.启动线程
4.终止线程(不推荐手动终止)
cpu会随机执行里面的线程:主线程,自定义线程
线程的声明周期包括四个状态:新生状态,可运行状态,阻塞状态和死亡状态
多个线程处于可运行的状态(线程调度)
分配优先级 1的优先级最高,默认值是5,Thread.currentThread().getPriority()
更改优先级 new Thread().setPriority(4)
new Thread().join()添加进阻塞进程
Thread.sleep(500)当前线程停止执行,进入不可运行状态(阻塞),其他等待运行的进程机会是相等的
yield当前线程转入暂停运行的状态(不阻塞),如果没有其他等待执行的线程,当前线程会马上恢复执行,会优先级相同的或更高的执行
线程同步
关键字synchronized
同步方法
同步代码块
线程通信
wait()挂起当前线程,并释放共享资源的锁
notify()在因调用该对象的wait方法二阻塞的线程中随机选择一个解除阻塞,但要等到获得锁后才可以正真执行
notifyall将因调用该对象的wait方法而阻塞的所有线程一次性全部解除阻塞
这三个方法只能在同步方法或者同步代码块中使用
线程创建
//1.定义线程:通过继承的方式 public class MyThread extends Thread{ //重写run @Override public void run() { for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); } } public static void main(String[] args) { //cpu会随机执行里面的线程:主线程,自定义线程 //2.创建线程对象 MyThread myThread = new MyThread(); //3.启动线程 myThread.setName("我的线程");//定义线程名 myThread.start(); //主线程 for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); } } }
public class MyRun implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { // MyRun myRun = new MyRun(); // new Thread(myRun,"自定义线程名").start();//Thread才是真正的线程 // // //主线程 // for (int i = 0; i < 5; i++) { // //当前运行的是哪个线程 // System.out.println(Thread.currentThread().getName()+":"+i); // } //优先级只是cpu执行该线程的一个重要参考要素之一 MyRun myRun = new MyRun(); Thread t1 = new Thread(myRun, "线程1"); Thread t2 = new Thread(myRun, "线程2"); t1.setPriority(4); t2.setPriority(6); t1.start(); // t2.start(); for (int i = 0; i < 5; i++) { //当前运行的是哪个线程 System.out.println(Thread.currentThread().getName()+":"+i); Thread.sleep(500); } } }
分苹果
public class ShareApple implements Runnable { private int count = 5;//苹果的总数 private boolean flag = true;//标记位,是否可以拿苹果 //拿苹果的方法 //同步方法 public synchronized boolean getApple() { // synchronized (this) {//同步代码块 if (count == 0)//是否有苹果 return false; count--; try { Thread.sleep(800); } catch (InterruptedException e) { e.printStackTrace(); } if (count >= 0) { System.out.println(Thread.currentThread().getName() + "成功拿到了一个苹果,还剩" + count + "个苹果"); } else { System.out.println(Thread.currentThread().getName() + "没有拿到苹果"); } return true; // } } @Override public void run() { while (flag) flag = getApple(); if (count == 0) { System.out.println(Thread.currentThread().getName() + "线程结束"); } } }
public class TestApple { public static void main(String[] args) { ShareApple shareApple = new ShareApple(); new Thread(shareApple,"小明").start(); new Thread(shareApple,"小黑").start(); } }
存取款
public class Account { private int balance = 500; public int getBalance() { return balance; } public void qu(int atm) { balance -= atm; } }
public class TestAccount implements Runnable { private Account account = new Account(); @Override public void run() { for (int i = 0; i < 4; i++) { makeWithDraw(100); if (account.getBalance() < 0) System.out.println("账户透支"); } } private void makeWithDraw(int atm) { synchronized (account) { if (account.getBalance() >= atm) { System.out.println(Thread.currentThread().getName() + "\t准备取款!"); account.qu(atm); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"\t完成取款"); }else { System.out.println("余额不足以支付\t"+Thread.currentThread().getName()+"\t取款的余额为"+account.getBalance()); } } } public static void main(String[] args) { TestAccount testAccount = new TestAccount(); Thread p1 = new Thread(testAccount, "张三"); Thread p2 = new Thread(testAccount, "张三的妻子"); p1.start(); p2.start(); } }
生产者消费者模式
public class Consumer extends Thread {//消费者 private ShareData data; Consumer(ShareData data) { this.data = data; } @Override public void run() { char s; do { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } s = data.getChar(); } while (s != 'D'); } }
public class Producer extends Thread { private ShareData data; Producer(ShareData data) { this.data = data; } @Override public void run() { //专门生产 for (char i = 'A'; i <= 'D'; i++) { data.produce(i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }
public class ShareData { private char c; private boolean flag = false;//信号量 //生产资源 public synchronized void produce(char c) { while (flag) { try { System.out.println("生产资源:消费者还没有消费,需要等待消费者进行消费"); wait();//线程立即挂起,释放锁和cpu资源 } catch (InterruptedException e) { e.printStackTrace(); } } flag = true; notify(); this.c = c; System.out.println("生产资源:生产者已经生产了产品" + c + ",等待消费者消费"); } //消费资源 public synchronized char getChar() { while (!flag) { try { System.out.println("消费资源:生产者还没有生产,无法消费消费。。。"); wait();//线程立即挂起,释放锁和cpu资源 } catch (InterruptedException e) { e.printStackTrace(); } } flag = false; notify(); System.out.println("消费资源:消费者消费了产品" + c + "通知生产者生产"); return c; } }
public class TestConsumer { public static void main(String[] args) { ShareData data = new ShareData(); new Producer(data).start(); new Consumer(data).start(); //定义了两个线程:每一次 都来争夺cpu资源 } }
死锁
public class DeadLockRunnable implements Runnable { //编号 public int num; //资源 private static Object chopsticks1 = new Object(); private static Object chopsticks2 = new Object(); private boolean flag =false;//信号量 /** * num = 1 拿到chopsticks1 等待chopsticks2 * num = 2 拿到chopsticks2 等待chopsticks1 */ @Override public void run() { if (num==1){ System.out.println(Thread.currentThread().getName()+"拿到了chopsticks1,等待chopsticks2"); synchronized (chopsticks1){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (chopsticks2){ System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } else if (num==2){ System.out.println(Thread.currentThread().getName()+"拿到了chopsticks2,等待chopsticks1"); synchronized (chopsticks2){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (chopsticks1){ System.out.println(Thread.currentThread().getName()+"用餐完毕"); } } } } }
public class DeadLockTest { public static void main(String[] args) { DeadLockRunnable deadLockRunnable1 = new DeadLockRunnable(); deadLockRunnable1.num=1; DeadLockRunnable deadLockRunnable2 = new DeadLockRunnable(); deadLockRunnable2.num=2; new Thread(deadLockRunnable1,"张三").start(); new Thread(deadLockRunnable2,"李四").start(); } }
线程通信
客户端与服务端
InetAddress类 无构造方法 getLocalHost获取本地ip getByName获取网络主机名
基于tcp:Socket(客户端)和Server Socket(服务器端)
ServerSocket.accept():获取客户端socket
Socket通信模型
进行网络通信是,Socket需要借助数据流来完成数据的传递工作
Socket类
两个Socket类的构造方法及其含义
Socket socket=new Socker(“localhost”,8800)
ServerSocket serverSocket = new ServerSocket(9000);
socket.getOutputStream();
os.write
1.建立连接
2.打开Socket关联的输入输出流
3.数据流中读写信息
4.关闭所有的数据流和Socket
ServerSocket类的accept()方法有何用处:获取客户端socket
import java.io.IOException; import java.io.InputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; public class Client { public static void main(String[] args) throws IOException {//客户端 //创建Socket Socket socket = new Socket(InetAddress.getLocalHost(),9000); //得到输出流 OutputStream os = socket.getOutputStream(); //写入字符串 // String msg="你好,服务器端,这是用户登录信息"; // os.write(msg.getBytes(StandardCharsets.UTF_8)); //写入对象 ObjectOutputStream objectOutputStream = new ObjectOutputStream(os); User user = new User("Jack","123"); objectOutputStream.writeObject(user); //告诉服务器,消息发完了 socket.shutdownOutput(); //得到输入流 InputStream is = socket.getInputStream(); //读取信息 byte[] by = new byte[1024]; int len ;//= is.read(by); String content=null; //超过1kb while ((len=is.read(by))!=-1){ content=new String(by,0,len); } System.out.println("客户端发送的信息是:"+content); //告诉服务器,消息发完了 // socket.shutdownOutput(); //关闭 is.close(); os.close(); socket.close(); } }
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class MyServer { public static void main(String[] args) throws IOException, ClassNotFoundException { //1.创建的是ServerSocket,指定对应的端口号 System.out.println("服务器请求链接"); ServerSocket serverSocket = new ServerSocket(9000); //2.等待链接 Socket socket = serverSocket.accept(); System.out.println("服务器等待链接"); //3.得到输入流,其实就是客户端的输出流 InputStream is = socket.getInputStream(); //4.1读取字符串信息 // byte[] by = new byte[1024]; // int len;//= is.read(by); // String content = null; // //超过1kb // while ((len = is.read(by)) != -1) { // content = new String(by, 0, len); // } // System.out.println("客户端发送的信息是:" + content); //4.2读取对象 ObjectInputStream ois = new ObjectInputStream(is); User user = (User) ois.readObject(); String msg2=null; if ("123".equals(user.getPassword())){ msg2="欢迎你"+user.getUsername(); }else { msg2="用户名或密码错误"; } System.out.println(msg2); //得到输出流,对客户端进行响应 OutputStream os = socket.getOutputStream(); String msg = "你好,客户端,信息已经收到"; //writer os.write(msg.getBytes(StandardCharsets.UTF_8)); //5.关闭资源 is.close(); os.close(); socket.close(); serverSocket.close(); } }
import java.io.Serializable; public class User implements Serializable { private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
服务器端与多客户端
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class LoginServer {//多线程处理客户端 public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9000); Socket socket; System.out.println("服务器等待请求。。。。"); while (true) {//实现一直监听 socket = serverSocket.accept(); System.out.println("服务器接收到请求"); //多线程 LoginThread thread = new LoginThread(socket); thread.start(); } } }
import java.io.*; import java.net.InetAddress; import java.net.Socket; public class LoginClient1 { public static void main(String[] args) throws IOException { User user = new User("张三", "123"); Socket socket = new Socket(InetAddress.getLocalHost(), 9000); OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); ObjectInputStream ois = new ObjectInputStream(is); System.out.println("我是客户端1,给服务器发送登录信息。。。"); oos.writeObject(user); //告诉服务已经发送完了消息 socket.shutdownOutput(); //接收服务器的信息 byte[] temp = new byte[1024]; int len = is.read(temp); System.out.println("服务器的响应"+new String(temp,0,len)); socket.close(); } }
import java.io.*; import java.net.InetAddress; import java.net.Socket; public class LoginClient2 { public static void main(String[] args) throws IOException { User user = new User("李四", "123"); Socket socket = new Socket(InetAddress.getLocalHost(), 9000); OutputStream os = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); InputStream is = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(is); System.out.println("我是客户端2,给服务器发送信息"); oos.writeObject(user); //告诉服务已经发送完了消息 socket.shutdownOutput(); //接收服务器的信息 byte[] temp = new byte[1024]; int len = is.read(temp); System.out.println("服务器的响应"+new String(temp,0,len)); socket.close(); } }
import java.io.*; import java.net.Socket; import java.nio.charset.StandardCharsets; public class LoginThread extends Thread { private Socket socket; public LoginThread(Socket socket) { this.socket = socket; } @Override public void run() { //处理客户端请求 try (//写在小括号里会自动关闭资源close InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); ObjectInputStream ois = new ObjectInputStream(is); ) { //得到客户端的信息 User user = (User) ois.readObject(); //给客户端回信息 String msg = null; if (user == null) { msg = "没有发送登录信息,登录失败"; } else { msg = "欢迎你" + user.getUsername(); } System.out.println(msg); os.write(msg.getBytes(StandardCharsets.UTF_8)); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
网络编程
ip地址与主机名
C类地址(192.0.0.0-223.255.255.0):192.168.0.0~192.168.255.255
InetAddress类 无构造方法 getLocalHost获取本地ip getByName获取网络主机名
基于tcp:Socket(客户端)和Server Socket(服务器端)
ServerSocket.accept():获取客户端socket
Socket通信模型
进行网络通信是,Socket需要借助数据流来完成数据的传递工作
Socket类
两个Socket类的构造方法及其含义
Socket socket=new Socker(“localhost”,8800)
ServerSocket serverSocket = new ServerSocket(9000);
socket.getOutputStream();
os.write
1.建立连接
2.打开Socket关联的输入输出流
3.数据流中读写信息
4.关闭所有的数据流和Socket
ServerSocket类的accept()方法有何用处:获取客户端socket
import java.net.InetAddress; import java.net.UnknownHostException; public class TestAddress { public static void main(String[] args) throws UnknownHostException { //InetAddress:IP地址包装类 InetAddress localHost = InetAddress.getLocalHost(); System.out.println(localHost.getHostAddress());//ip地址 System.out.println(localHost.getHostName());//主机名 //得到网络主机名 InetAddress address = InetAddress.getByName("www.baidu.com"); System.out.println(address.getHostAddress()); System.out.println(address.getHostName()); } }
UDP
基于UDP协议的Socket编程
1.利用DatagramSocket发送数据包
2.利用DatagramPacket对象封装数据包
3.利用DataGramPacket处理数据包
4.利用DataGramPacket接收数据包
建立发送端,接收端
创建数据
建立数据包
调用Socket的发送接收方法
关闭SOcket
发送端与接收端是两个独立运行的程序
import java.io.IOException; import java.net.*; import java.nio.charset.StandardCharsets; public class UDPSend {//发送端 public static void main(String[] args) throws IOException { DatagramSocket ds = new DatagramSocket(); byte[] msg = "最新的邮件来了。。。。".getBytes(StandardCharsets.UTF_8); //创建数据包,即将发送出去的数据包,发送的内容,收获的ip,端口号, DatagramPacket dp = new DatagramPacket(msg, 0, msg.length, InetAddress.getByName("localhost"), 9000); //发送数据 ds.send(dp); //关闭资源:socket ds.close(); } }
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class UDPReceive { public static void main(String[] args) throws IOException {//接收端 //1.创建DatagramSocket DatagramSocket ds = new DatagramSocket(9000); //2.创建Packet byte[] temp = new byte[1024]; DatagramPacket dp = new DatagramPacket(temp, temp.length); //3.接收数据 ds.receive(dp); //发送方的主机名 String hostName = dp.getAddress().getHostName(); //发送方的端口号 int port = dp.getPort(); System.out.println("发送方的主机名是"+hostName+"发送方的端口号是"+port); byte[] bytes = dp.getData();//获取接收到的内容 String msg=new String(bytes,0, dp.getLength()); System.out.println("发送过来的信息是:"+msg); //4.关闭资源 ds.close(); } }
DOM文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE students SYSTEM "student.dtd"> <students> <student id="1"> <name>王同</name> <class>java</class> <score>89</score> </student> <student id="2"> <name>李佳</name> <class>sql</class> <score>58</score> </student> <student id="3"> <name>李白</name> <class>python</class> <score>90</score> </student> </students>
<!ELEMENT students (student+)> <!ELEMENT student (name,class,score)> <!ATTLIST student id CDATA #IMPLIED> <!ELEMENT name (#PCDATA)> <!ELEMENT class (#PCDATA)> <!ELEMENT score (#PCDATA)>
public class TestXML { public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException { //1.得到document DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); //2.解析和加载xml文件到内存中去 Document document = documentBuilder.parse("student.xml"); //3.返回文档中的所有子节点 NodeList nodeList = document.getChildNodes(); Node root = nodeList.item(nodeList.getLength() - 1); System.out.println("root:" + root.getNodeName());//students //4.再查找他的子节点 NodeList childNodes = root.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node item = childNodes.item(i); if ("student".equals(item.getNodeName())) { NodeList nodes = item.getChildNodes(); for (int j = 0; j < nodes.getLength(); j++) { Node node = nodes.item(j); if ("name".equals(node.getNodeName())) { System.out.println("name:" + node.getTextContent()); } else if ("class".equals(node.getNodeName())) { System.out.println("class:" + node.getTextContent()); } else if ("score".equals(node.getNodeName())) { System.out.println("score:" + node.getTextContent()); } } } } } }
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.FileOutputStream; import java.io.IOException; public class UpdateXML { public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException { //使用DOM对XML文件进行数据修改 //1.得到document DocumentBuilderFactory dbf; dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); //解析和加载xml文件到内存中去 Document document = documentBuilder.parse("student.xml"); //1.删除某个节点 // NodeList list = document.getElementsByTagName("student"); // for (int i = 0; i < list.getLength(); i++) { // Element item = (Element)list.item(i); // //node:节点(文本节点),element:元素 // //凡是元素都是节点,但是节点不一定都是元素,例如:一个单纯的回车也是节点 //// System.out.println(item.getAttribute("id")); // if ("2".equals(item.getAttribute("id"))){ // item.getParentNode().removeChild(item); // } // } //2.添加节点 // //student(name class score) // Element student = document.createElement("student"); // student.setAttribute("id", "3");//设置属性值 // //name // Element stuName = document.createElement("name");//创建节点 // stuName.setTextContent("李白");//设置节点内容 // student.appendChild(stuName);//添加节点 // //class // Element stuClass = document.createElement("class"); // stuClass.setTextContent("python"); // student.appendChild(stuClass); // //score // Element stuScore = document.createElement("score"); // stuScore.setTextContent("90"); // student.appendChild(stuScore); // //找到根节点students // NodeList nodeList = document.getElementsByTagName("students"); // Node students = nodeList.item(nodeList.getLength() - 1); // students.appendChild(student); //修改:李白-》李清照 //1.查找节点 NodeList student3 = document.getElementsByTagName("student"); for (int i = 0; i < student3.getLength(); i++) { Element item = (Element)student3.item(i); if ("3".equals(item.getAttribute("id"))){ Node name = item.getElementsByTagName("name").item(0); //2.修改节点内容 name.setTextContent("李清照"); break; } } //保存成XML文件 TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource domSource = new DOMSource(document); // 设置编码类型 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); StreamResult result = new StreamResult(new FileOutputStream("student.xml")); // 把DOM树转换为XML文件 transformer.transform(domSource, result); } }
DOM4j
<?xml version="1.0" encoding="UTF-8"?> <books> <book id="book1"> <name>三国演义</name> <price>99.88</price> </book> <book id="book2"> <name>西游记</name> <price>77.88</price> </book> <book id="book3"> <name>李白的诗</name> <price>88.88</price> </book> </books>
import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.util.Iterator; import java.util.List; public class TestDom01 { public static void main(String[] args) throws DocumentException { SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); System.out.println(root.getName());//root //遍历显示所有的数据 List<Element> list = root.elements("book"); for (Element book:list){ Attribute id = book.attribute("id"); System.out.println("id:"+id.getValue()); //迭代器 Iterator<Element> it = book.elementIterator(); while (it.hasNext()){ Element element = it.next(); System.out.println(element.getName()+":"+element.getText()); } System.out.println("----------------"); } } }
import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import java.io.FileWriter; import java.io.IOException; import java.util.List; public class TestDom02 { public static void main(String[] args) throws DocumentException, IOException { //需求:实现 删除 id="book3"这样的一个节点 /* <book id="book"> <name>李白的诗</name> <price>88.88</price> </book> */ //解析xml文件 SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); //找到相应的节点 List<Element> bookList = root.elements("book"); for (Element book:bookList){ Attribute id = book.attribute("id"); if ("book3".equals(id.getValue())){ book.getParent().remove(book);//删除 } } //保存到xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileWriter("books.xml")); writer.write(doc); writer.close(); System.out.println("删除成功"); } }
import org.dom4j.*; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import java.io.FileWriter; import java.io.IOException; import java.util.List; public class TestDom03 { public static void main(String[] args) throws DocumentException, IOException { //需求:实现 新增节点 /* <book id="book"> <name>李白的诗</name> <price>88.88</price> </book> */ //解析xml文件 SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); //新增节点 Element book = DocumentHelper.createElement("book"); book.addAttribute("id", "book3"); Element name = DocumentHelper.createElement("name");//创建节点 name.setText("李白的诗");//设置属性 book.add(name);//添加节点 Element price = DocumentHelper.createElement("price"); price.setText("88.88"); book.add(price); root.add(book); //保存到xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileWriter("books.xml")); writer.write(doc); writer.close(); System.out.println("新增成功"); } }
import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Iterator; import java.util.List; public class TestDom04 { public static void main(String[] args) throws DocumentException, IOException { //需求 实现 修改 id="book3"这样的一个节点 李白的诗-》李清照的诗句2.外部类外部:StaticInnerClass.Inner inne SAXReader saxReader = new SAXReader(); Document doc = saxReader.read("books.xml"); //得到根节点 Element root = doc.getRootElement(); System.out.println(root.getName());//root //遍历所有的数据 List<Element> list = root.elements("book"); for (Element book : list) { //找到对应的节点 if ("book3".equals(book.attribute("id").getValue())) { //迭代器 Iterator<Element> it = book.elementIterator(); while (it.hasNext()) { Element element = it.next(); //找到要修改的文本 if ("李白的诗".equals(element.getText())) { element.setText("李清照的诗"); System.out.println(element.getName() + ":" + element.getText()); break; } } break; } } //保存到xml文件 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileWriter("books.xml")); writer.write(doc); writer.close(); System.out.println("修改成功"); } }
集合
2.外部类外部:StaticInnerClass.Inner inne
import java.util.HashSet; import java.util.Set; public class Worker { private String name;//姓名 private int age;//年龄 private int salary;//收入 public Worker(String name, int age, int salary) { this.name = name; this.age = age; this.salary = salary; } @Override public String toString() { return "Worker{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } @Override public int hashCode() { // TODO Auto-generated method stub return this.name.hashCode() + age + salary; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (this.getClass() != obj.getClass()) { return false; } Worker obj2 = (Worker) obj; if (this.name.equals(obj2.name) && this.age == obj2.age && this.salary == obj2.salary) { return true; } return false; } public static void main(String[] args) { Set<Worker> hashSet = new HashSet<>(); //hashcode作为索引或者说是唯一标识 hashSet.add(new Worker("zhang3", 18, 1500)); hashSet.add(new Worker("li4", 18, 1500)); hashSet.add(new Worker("wang5", 18, 1600)); hashSet.add(new Worker("zhao6", 18, 2000)); hashSet.add(new Worker("zhao6", 18, 2000)); for (Worker worker : hashSet) { System.out.println(worker); } } }
import java.util.HashSet; import java.util.Set; import java.util.TreeSet; public class Worker implements Comparable { private String name;//姓名 private int age;//年龄 private int salary;//收入 public Worker(String name, int age, int salary) { this.name = name; this.age = age; this.salary = salary; } 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 int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } @Override public String toString() { return "Worker{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; } @Override public int compareTo(Object o) { if (this == o) { return 0; } else { if (o instanceof Worker) { Worker worker = (Worker) o; if (this.age != worker.getAge()) { return this.age - worker.getAge(); } else if (this.salary != worker.getSalary()) { return this.salary-worker.getSalary(); } else { return this.name.compareTo(worker.getName()); } } else { try { throw new Exception("只能比较Worker对象"); } catch (Exception e) { e.printStackTrace(); } } } return 0; } public static void main(String[] args) { TreeSet<Worker> set = new TreeSet<>(); set.add(new Worker("zhang3", 18, 1500)); set.add(new Worker("li4", 18, 1500)); set.add(new Worker("wang5", 18, 1600)); set.add(new Worker("zhao6", 17, 2000)); for (Worker worker : set) { System.out.print(worker.getName()+"\t"); } } }