18-11-11:同类不同对象的方法指向一个区、成员变量与局部变量、私有化、构造方法及其重载.txt****
两个对象所指向的方法是同一个地址:
如果有两个对象p1,p2,他们的方法其实都是放在方法区中。而他们的对于共同指向此方法
成员变量和局部变量区别:
位置:成员变量是在类中声明的局部变量是在方法体中或者形式参数中声明内存:成员变量是在堆中局部变量是在栈中 初始化值:成员变量因为是在堆中所以有初值局部变量在栈中,所以声明后必须要先赋值才能使用
private修饰符:
放置位置:放在变量或方法的最前面作用:被修饰后的变量或方法只可以在本类中使用,在外类不可见。这样可以保证数据安全配合:被private修饰了的变量一定要有对应的setXxx() 和 getXxx()公有方法
构造方法:
格式:public Student(...){ //与类名同名,且没有返回类型。}调用构造方法:Student s = new Student(..) //其实new后面的就是调用了一个类的构造方法构造方法的注意事项与重载:如果没有构造方法,则系统会自动提供一个无参数的构造方法。如果有了带参数的构造方法,无参构造方法就要自己构造。推荐只要写一个类,就要有一个无参构造方法
18-11-12:方法的形参和返回值可以是对象、API、==详解、String对象初步、直接赋值和new字符串对象区别.txt****
类中的方法的形式参数和返回值可以是一个对象:
形参-例如:public void UseStudent(Student s){System.out.println("我是个老师,现在调用学生的方法");s.speak();}返回值-例如:public Student getStudent(){ //返回类型是类,则返回对象Student s = new Student();return s;}
API的使用:
API就是帮助文档
==:
如果是基本数据类型则比较的是值是否相等。如果是引用数据类型则比较的是地址是否相等。
String对象初步:
String是个特殊的引用类型对象syso(str) //一般来说打印引用类型变量结果为其引用值,而打印字符串类型对象则直接打印结果new出的字符串对象和直接赋值的字符串对象的区别比较:new方式:new出来的依然是在堆内存,但是字符串的内容在方法区的常量池中。栈中的引用变量存了堆的地址,而堆中对象是存的常量池的地址。直接赋值:栈中的引用变量直接存的是常量池中的地址。常量池:字符串一般存在方法区当中的常量池中,同一个字符串在常量池中的位置唯一举例1:String s1 = "hello";String s2 = new String("hello");System.out.println(s1==s2); //false原因分析:s1存的是常量池当中的002;s2存的是堆中的001,堆中的001在存的是常量池中的002;001 != 002 所以false举例2:String s1 = "hello";String s2 = "hello";System.out.println(s1 == s2); //true原因分析: s1和s2存的都是常量池中的002,所以相等。注意: 因为字符串对象也是引用数据,所以在进行==比较的是地址的值。如果要比较字符串的值是否相等,则用s1.equals(s2)
//明天内容
String中的成员方法:
一:判断s1.equals(s2)s1.equalsIgnoreCase(s3) //忽略大小写
18-11-13:字符串的方法、主类中的方法注意事项提醒、next与nextLine区别.txt****
String对象的判断方法:
s1.equals(s2)s1.equalsIgnoreCase(s2) //忽略大小写s1.endsWith("lo")s1.startWith("he") //判断开头和结尾字符串
String的获取方法:
s.length() //注意,对于数组来说是a.lengths.charAt(1) //根据所以获取字符,返回的是单个字符s.substring(0, 5) //从0到4,截取字符串 左闭右开字符串的遍历:for(int i = 0; i < s.length(); i++){System.out.println(s.charAt(i));}
String的转化功能:
转化成字符数组:char[] chs = s.toCharArray();System.out.println(chs); //字符数组打印的是一个值,有别于其他数组,其他数组打印的是引用地址值。for(int i = 0; i < chs.length; i++){System.out.println(chs[i]);} 转化成字符串小写LowerCase()转化成字符串大写UpperCase()
String的其他操作:
关于主类中的方法注意事项:
测试类(主类)中的方法一定要写成public static 类型 方法名(..){}而类中的方法一定要写成public 类型 方法名(..){}
关于与Line方法区别:
注意,不管怎么输入,回车是指输入完毕!next只节选空格前的内容nextLine是节选输入的一行的内容
18-11-14:StringBuilder的构造方法、添加与反转、链式编程、与字符串的相互转化.txt****
StringBuilder与String的区别:
为什么要有StringBuilder?:因为每一次的字符串拼接都会浪费时间和存储空间,造成内存垃圾。而StringBuilder是一个可变的字符串对象,合理的解决了这个问题。
StringBuilder构造方法及其容量和长度:
StringBuilder sb = new StringBuilder(); //默认构造方法,长度为16sb.length() // 此字符串的字符个数sb.capicity() // 该对象的容量值,理论容量
StringBuilder的添加方法及其反转功能:
StringBuilder sb = new StringBuilder();//字符串的添加方法,链式编程。sb.append("hello").append("world").append(true).append(100); //append方法不管添加什么都可以,且sb对象直接可变。System.out.println(sb); //结果:helloworldtrue100//字符串的反转方法sb.reverse(); //reverse方法也是可以直接可变的。System.out.println(sb); //结果:001eurtdlrowolleh
StringBuilder 与 String的相互转化:
/** String 与 StringBuilder的相互转化:这样可以通用各自的方法*///String转化成StringBuilder:通过构造方法String s = "hello";StringBuilder sb = new StringBuilder(s);System.out.println(sb);//将StringBuilder转化成String:调用sb对象的toString方法StringBuilder sb2 = new StringBuilder("hahah");String s2 = String();System.out.println(s2);
18-11-16:ArrayList集合及其相关操作、缓冲流的问题提出.txt****
ArrayList:
缘由:因为此类是一个可以变化的数组,更加贴近实际应用。初始化:ArrayList<String> List = new ArrayList<String>(); //<>当中的是范型,这里以String举例。添加元素方法:boolean add(E e) 将指定的元素添加到此列表的尾部。 void add(int index, E element) 将指定的元素插入此列表中的指定位置。 打印:System.out.println(List); //结果:[C++, java, python, perl, php] 不同于其他引用类型变量,和String一样,直接打印值。长度、删除、修改、获取等方法:E set(int index, E element) //修改int size() //长度E get(int index) //获取E remove(int index) //删除boolean remove(Object o) //删除遍历:通过size方法和get方法对其进行遍历。for(int i = 0; i < List.size(); i++){String s = (i);System.out.println(s);}
为什么输入数字以后不能输入字符串?
输入数字以后会有个空白字符留在缓冲流之中,这个时候打一个 Line()就可以解决这个问题。具体内容以后再说。
18-11-16:StringBuilder的内容补充.txt****
利用StringBuilder 判断是否为对称字符的注意:
public static boolean isReverse(String s){StringBuilder sb = new StringBuilder(s);sb.reverse();return sb.equals(s); //sb和s是不同的对象,不管怎么样都返回是false。} //改成 String().equals(s) 就可以了
由于SB对象是一个可变的引用数据,故两个变量引用同一个对象时互相影响:
StringBuilder sb = new StringBuilder("abc"); StringBuilder s = sb; //s也指向sb的对象s.reverse(); //将s反转System.out.println(sb); //sb也被反转了。结果:cba
18-11-18:IO流fw和fr的使用、br和bw的使用、文本复制、nextInt后不能直接nextLine的解释.txt****
IO流
简述:
用于数据的读取和存储输入流:从文件中读取数据输出流:将数据存储在文件当中
FileWriter的基本使用:
public class IODemo {public static void main(String[] args) throws IOException {//创建fw对象,注意路径的格式是\FileWriter fw = new FileWriter("D:\1.txt");//写入内容fw.write("大家好我是熊汝成hahaha");//写入的内容还在内存缓冲区,需要进行刷 新才能将内容填入文件当中fw.flush();//关闭文件fw.close();}}
flush与close的区别:
flush是刷新内存缓冲区的内容,让其内容填入到文件当中close是先将进行flush的功能,在将文件关闭
追加与换行:
如果需要追加内容就是:FileWriter fw = new FileWriter(",true);如果需要换行:直接fw.write("n"); //windows的记事本无法显示,需要加一个rn
读取数据:
int ch; //fr.read返回int,是什么类型就用什么类型接收while((chad())!=-1){System.out.print((char)ch); //将int类型强制转化成char}
一次读取多内容数据:
FileReader fr = new FileReader(");char[] chs = new char[1024]; //默认定义为1024的整数倍int len;while((lenad(chs))!=-1){ //fr.read(chs) 将返回获取的内容的实际长度,-1表示没有内容了System.out.print(new String(chs,0,len)); //将字符数组转化成字符串}
复制文本内容-两种方式进行比较:
public static void copyBySoloChar(FileWriter fw,FileReader fr) throws IOException{ //单个字符int ch; //ch是每一个字符的编码值while((chad())!=-1){fw.write(ch);}}public static void copyByCharArray(FileWriter fw,FileReader fr) throws IOException{ //以字符数组char[] chs = new char[1024]; //获取的每一个字符放在数组中int len; //len是获取的实际长度while((lenad(chs))!=-1){fw.write(chs, 0, len); //将实际获取的文本写入到文件中}}
缓冲流:
相比于FileWriter与FileReader更加高效构造方法:BufferedWriter bw = new BufferedWriter(new FileWriter("));BufferedReader br = new BufferedReader(new FileReader(")); //构造方法里边的是fw或者fr对象
bw与br对象的特殊功能:
bw的特殊功能:for(int i = 0; i < 10; i++){bw.write(i+""); //将i转化成字符串bw.newLine(); //特殊的换行功能}br的特殊功能:String line;while((lineadLine())!=null){ //每次读取一行中换行符前面的内容System.out.println(line);}
利用特殊功能进行文本复制: //必须掌握
String line;while((lineadLine())!=null){bw.write(line);bw.newLine();}bw.close();br.close();
关于nextInt后面为什么不能用nextLine:
使用nextInt会将换行符前面的数字输入进去,而换行符留在了缓冲区。使用nextLine会将缓冲区中包括换行符在内的内容输入进去。由于nextInt后还有个n在缓冲区,当执行nextLine后就将n输入了进去,于是就造成了问题。改进:x = Int();Line(); //用于缓冲s = Line;
18-11-20:IO流的定位、static关键字、代码块.txt****
IO流的定位:
File file = new File("); //定义一个文件对象BufferedReader br = new BufferedReader(new FileReader(")); //构建一个缓冲输入流br.mark((int)file.length()+1); //先开始,光标指在文章的开头,现在在此处标记一下,参数是字符个数,如果光标输出字符数>=该值,则无法返回到标记处br.reset(); //让光标回到标记的位置
static关键字:
被static修饰的属性特点:被对象共享,一个对象的该属性变了,其他对象的该属性也跟着变了。可以直接由类名调用。注意事项:静态方法只能用静态的属性和方法。非静态方法什么都可以调。静态的方法里不可以有this关键字。原因:静态的方法和属性是随着类的加载而生成的,此时对象还没有出现,那些非静态属性和方法也没有生成。为什么主类中的方法都是静态的?:因为主方法是静态的,上面也提到静态方法只能调用静态的,所以主类中的方法也是静态的。静态的意义:如果将属性、方法都定义为静态的,将构造方法也私有(无法创造对象),此类就是一个工具类。由于不需要创造对象,靠类名就能直接调用。
代码块:
就是大括号,大括号里面的变量不能出去使用。构造代码块和静态代码块:主要是在创造类的对象时做的初始化工作,可能构造方法过多,所以将构造方法中同样的初始化方法放在代码块中例如:{System.out.println("老师对象创立成功"); //代码块,没创造一个对象就会调用}public Teacher(){System.out.println("我是无参");}public Teacher(String name, int age){System.out.println("我是有参");this.name = name;this.age = age;}结果: //类中代码块的执行早于构造方法,如果代码块换成static{},则"老师对象创立成功"只执行一次老师对象创立成功我是无参老师对象创立成功我是有参
18-11-21:继承的原因、继承中属性和方法的特点、方法重写注意事项、构造方法的继承问题.txt****
继承:
为什么要用到继承:如果很多个类有相同的部分,可以将相同的部分抽取出来变成一个父类。再让这些类继承于父类。java中继承的特点:只能单继承。可以多层继承继承中成员变量的特点:1:子类只能继承父类中的非私有属性,对于私有属性无法继承,但可以继承父类中的pulic getElement()方法,间接获取父类的私有属性。2:Father中有一个name,且Son中也有一个name,可让Son类通过super关键字访问父类中的name,也可以访问其他属性和方法,具体用法类似于this继承中成员方法的特点:1.子类只能继承父类中的非私有方法,对于私有方法无法继承2.如果子类中的方法和父类中的方法完全相同,这叫做方法重写。一般是父类的方法无法满足子类的需求,也可以通过super硬性调用父类方法方法重写的应用场景和注意事项:通过注解@Override可以得到以下的结论:1:方法重写的必须是父类中完全一样的方法!只是代码块中的东西可能不一样!2:继承的方法权限必须宽松或者等于父类中的方法权限。(一般权限相等)构造方法的继承:不管如何,在初始化子类前肯定会先初始化父类,因为子类可能要用到父类的初始化东西。(重点)子类中的构造方法如果没有写super和this关键字,则会默认调用父类的无参构造。如果想改变默认构造,可在子类构造方法中调用super(...)关键字
18-11-22:抽象类及其注意事项、final关键字、修饰符位置问题.txt****
抽象:
为什么要抽象:dog和cat都有eat方法,但eat不同的东西。如果直接继承Animal的eat无法满足,所以将Animal的eat方法抽象化,再让dog、cat去具体实现。abstract 关键字:修饰类和方法。一般放在public 的后面(当然放在public前面也没关系)例如:public abstract class Animal{}public abstract void eat();注意点:1.含抽象方法的类必定是抽象类,必须要用abstract去修饰类和方法。2.抽象类的子类要么完全实现父类的所有抽象方法,要么也定义为一个抽象类。3.抽象类中可以有非抽象方法。4.抽象类不可以实例化,即不可用抽象类来创建对象。抽象类中的成员特点:1.抽象类中可以有属性。2.抽象类中可以有抽象方法也可以有具体方法。3.抽象类虽然不能实例化但是也可以有构造方法。因为初始化子类前要初始化父类。4.抽象类不能是final类。因为final类没办法被继承,而abstract必须有子类实现。5.抽象类可以有常量(即final属性)
final:
1:被final修饰的属性是常量,最好一开始就赋值(也可以在构造方法中赋值)。一旦赋值不可再次修改。2:被final修饰的方法无法被子类重写。3:被final修饰的类无法被继承。
有关修饰符的位置问题:
public static abstract final 这几个修饰符的位置放置关系没有关系。但方法名的前面必须是返回类型便可。
抽象类也可以继承一个普通类。
18-11-25:多态、上下转型对象.txt****
多态:
概念:如果父类的引用指向了子类的实体,这时同种类型调用同种方法可能会出现不同的现象,这种现象叫多态。前提:1.有子父类。2.父类引用指向子类实体。上转型和下转型:上转型:父类引用指向子类对象。Father ob = new Son(); //称ob是new Son()的上转型对象。下转型:强制将上转型对象转化成子类对象。Son ob2 = (Son)ob; //将ob这个上转型对象强制转化成子类对象,并赋给子类对象ob2,这个时候ob2就是个正宗的Son对象了上转型对象的成员特点:1.成员变量:看左用左,父类必须有该变量,若子类有同名新变量,还是用的还是父类的成员变量。2.静态方法:看左用左,父类必须有该静态方法,若子类重写该方法,还是用的还是父类的该静态方法。3.成员方法:看左用右,父类必须有该方法,若子类重写该方法,用的是子类中重写后的方法!ps:看左是指父类中必须有这个玩意儿。否则无法通过编译器多态中的成员特点总结:调用成员方法和属性时父类必须要有该方法或属性,否则编译器无法通过。 (意思是不可调用子类新增)只有调用成员方法时是调用子类重写方法,其他的都是调用父类本有静态方法或属性。
18-11-25:接口、匿名对象.txt****
接口:
接口出现的原因:为了解决继承的单一性。有关接口的基本要点:1.接口是一个比抽象类还抽象的类,它的所有方法都是抽象方法。2.接口与类的关系不再是继承,而是实现。3.接口的定义格式就是将class换成interface。4.接口也可以用来申明变量。例如:Phone p; //其中Phone是一个接口,p一般是个上转型对象。接口的成员特点:1.对于成员属性,默认加上public static final修饰词,表示必须是一个可继承静态的常量。2.对于成员方法,默认加上public abstract 修饰词3.接口没有构造方法。4.同抽象类一样,如果实现接口时要么重写所有方法,要么也定义为一个抽象类。5.请将默认修饰符打出来。接口与类之间的关系:1.类与类:单继承。2.类与接口:多实现。3.接口与接口:多继承!4.一个类也可以同时继承和实现,不过要先继承后实现。 例如:class Final extends Student implements A {}
匿名对象:
没有变量引用:new Student() 这就是个匿名对象。应用场景:一般是一次性使用某个方法时用匿名对象。
18-11-26:权限修饰符、权限修饰符的使用规则.txt****
权限修饰符:
public 当前类中 当前包下不同类中 不同包下的不同类private 当前类中default 当前类中 当前包下不同类中protected 当前类中 当前包下不同类中
对于修饰符的场景使用:
1.一个java文件中只能有一个类,且该类是public类。2.所有的成员变量用private修饰。也要设置get、set方法。3.所有的方法都用public修饰。4.构造方法也都用public修饰,除非不想创建对象就用private修饰(工具类)。
18-11-27:Object中的toString、equals方法.txt****
Java高级API
1.String toString()方法:是Object中的方法,用于返回对象的地址。2.boolean equals(Object o) 是一个比较对象的地址值是否相等的方法。
18-11-27:内部类的使用.txt****
内部类:
成员内部类:1.成员内部类就是将内部类定义在外部类的成员位置当中。2.创建内部类对象前必须有外部类对象,所以定义格式是: Outer.Inner i = new Outer().new Inner();源码如下:public class MemberInnerClass {public static void main(String[] args) {Outer.Inner inner = new Outer().new Inner(); //创建内部类对象首先要有外部类对象inner.funInnerr(); }}class Outer{ //外部类 public void funOuter(){ //外部类的成员方法System.out.println("funOuter");}class Inner{ //内部类定义public void funInnerr(){ //内部类的成员方法System.out.println("funInner");}}3.修饰符:成员内部类可以直接用static修饰,这样就不需要外部类对象了。Outer.Inner inner = new Outer.Inner(); 局部内部类:1.局部内部类定义在外部类的方法体中。2.局部内部类所创建的对象也只能在外部类方法体中创建。3.局部内部类一般用的不多,只做了解内容源码如下: public class MemberInnerClass {public static void main(String[] args) {Outer o = new Outer();o.funOuter();}}class Outer{ //外部类public void funOuter(){class Inner{ //局部内部类的定义public void funInnerr(){System.out.println("funInner");}} Inner i = new Inner(); //局部内部类对象也只能定义在该方法之中。i.funInnerr();} }匿名内部类:1.格式: new 类/接口(){子类内容};2.代码块中是类的子类或者接口的实现类。3.功能与匿名对象相同,一次性调用。如果想多次调用,可以运用之前的向上转型对象原理。4.匿名内部类是同局部内部类一样必须放在方法体中。5.匿名内部类的应用场景是当一个对象作为参数传递一次时,为了不创建一个java文件,所以用匿名内部类对象。
18-11-28:Date类常用方法、SimpleDateFormat格式化日期.txt****
Date常用方法:
构造方法:1.Date d = new Date(); //默认获取当前系统时间2.Date d = new Date(long time) //将毫秒值传进去,设定指定时间对象常用方法:1. d.toString() //打印一个不友好时间2. d.toLocaleString() //打印一个友好时间,但已经过时3. d.setTime(long time) //设置时间4. d.getTime() // 获取时间毫秒
SimpleDateFormat日期格式化:
实例上演:public class DateDemo {public static void main(String[] args) {//按照指定模式创立的日期格式化对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E HH:mm:ss");//将Date日期传进去,就可以获取格式化当前时间字符串String s = sdf.format(new Date()); System.out.println(s); //结果:2018年11月28日星期三 17:31:48}}解析时间:Date d = sdf.parse("2018年10月28日星期三 17:31:48");System.out.LocaleString()); //结果:2018-10-28 17:31:48总结:sdf对象可以将Date对象的时间按指定格式化变成一个字符串(sdf.format()),也可以将指定格式化的字符串变成一个Date对象(sdf.parse()),它像一个中介,在Date对象 和 指定格式字符串 中相互转换。
18-11-29:Calendar类的基本使用.txt****
Calendar类的基本使用:
1.获取对象:Calendar c = Instance(); 2.获取时间:(Calendar.YEAR)) //Calendar.YEAR是一个字段,其实是该类的常量属性3.修改时间:c.set(int field, int value)4.增加时间:c.add(int field, int amount)
18-11-29:Collection接口概述.txt****
容器:
1.基本概念:可以装对象的东西。2.基本树:Collection(接口) --> Set(接口,无序不重复), List(接口,有序可重复) --> Map(接口,键值对存储)3.Collection接口中的基本方法:见API
18-11-29:包装类 Integer、字符串与整数的相互转换、自动装拆箱.txt****
包装类–Integer类的介绍:
核心内容是 int — String 的相互转化
int -> String:
方法1. number + "" // 最简单的方式方法2. Integer i = new Integer(10); //创立一个Integer对象,再调用对象的toString方法System.out.String() + 100); //10100方法3.String num_s = String(20) //调用该类的静态方法 public static String toString(int i) 。
String -> int:
方法1. Integer i = new Integer("100");syso(i + 400); //此时i就是一个int类型,结果为500(自动拆箱)方法2.Integer i = new Integer("100");int num = i.intValue(); //调用对象的方法方法3.int num = Integer.parseInt("1000"); //这是Integer的静态方法。
推荐:
int -> String : num + ""String -> int: Integer.parseInt(s)
自动装箱与自动拆箱:
装箱:基本数据类型变成包装类对象。拆箱:相反
自动装箱应用场景:
Integer i = 10; //将10这个基本数据类型转化成对象ArrayList list = new ArrayList(); list.add(1) ; //集合只能装对象,这里的1被自动装成对象
自动拆箱应用场景:
Integer i = 10; int num = i; //这里i被自动拆成基本数据类型,然后由基本数据类型接收
18-11-4:注释、变量、命名、转化.txt****
Java基础
·java跨平台:因为在不同的操作系统上有不同的jvm
jre:运行环境(包括jvm和核心类库)jdk:开发工具(包括了jre)
·注释:
// 单行注释/* */ 多行注释/** **/文档注释
·定义数据类型时的注意:
整形默认是int 浮点默认是double定义long时数字后加L定义float时数字后加F
·命名规则:
包:一定要小写,多级包用.分隔类:首字母大写方法和变量:首字母小写,后面每个单词首字母大写
·变量的域:
变量的使用,只能在其域中(此变量所在的大括号范围中)例如public class Main{public static void main(String args[]){{ /*代码块*/int c = 30;}System.out.print(c); //无法正常输出}}
·类型转换:
一般而言我们要求运算的类型一致如果不一致就会发生转换:隐式转换:byte、short、char -- int -- long -- float -- double (由低向高的转换顺序)参与运算的数据将自动转换成精度较高的数据,但高精度不可转化为低精度,避免造成缺失数据例如:byte a = 10;int b = 20;byte x = a + b; //b是int,a将转化成int,最终结果也为int,不可用低精度的变量接收int y = a + b;System.out.println(x);System.out.println(y);强制转换类型:强制将高精度转换成低精度,一般不这样做。例如: 如上byte x = (byte)(a + b); //这个时候就可以通过编译
18-11-5:字符串加法、双&、随机数、数组.txt****
·字符串参与加法运算
任何类型变量与字符串参与加法运算都是字符串的拼接System.out.println("a"+100); //a100System.out.println("a"+'e'); //ae
·&& 与 & 以及 || 与 | 在java中区别不大
但是&&在条件判断中如果前者为false后者不进行判断,而&无论如何两边都会去进行判断
·随机数
用 ctrl + shift + o 快捷键导包import java.util.Random; Random r = new Random();r.nextInt(100); //[0,100) 的随机数
·数组
基本使用int arr[] = new int[10]; //数组的初始化System.out.println(arr); //打印的是地址值 for(int i = 0; i < arr.length; i++){System.out.println(arr[i]); //每一个对象进行初始化时都有一个默认值,int的默认值是0}静态初始化:int[] a = {1,2,3};for(int e: a){ //类似于python的遍历System.out.println(e);}将数组赋值给数组int[] a1 = new int[3];int[] a2 = new int[10];for(int i = 0; i < a1.length; i++){ //对a1数组赋值a1[i] = i;}a2 = a1;System.out.println(a2.length); //尽管a2分配了10个空间,但a2这个变量指向了a1这个变量的地址,故a2的长度也变成了3for(int i = 0; i < a2.length; i++){a2[i] = 100 + i; //对a2进行赋值}for(int i = 0; i < a2.length; i++){System.out.println(a1[i]); //发现对a2的赋值影响到了a1}数组内存分配变量名放于栈中:int[] arr 对象放于堆中,每个对象都有默认值:new int[100] 遍历二维数组:int[][] a = {{1,2,3},{4,5,6},{7,8,9}};for(int i = 0; i < a.length; i++){for(int j = 0; j < a[i].length; j++){ //a[i]也是个数组System.out.print(a[i][j] + " ");}System.out.println();}
18-11-6:方法定义格式、方法重载、以及注意事项、方法参数是基本类型.txt****
·方法:
定义在主类当中格式:记住格式!public static int fun(int a, int b){}方法重载:定义:同一个类中出现了名字相同的方法参数特点:同名方法参数个数不一样同名方法参数类型不一样如果不满足以上两点:则报错注意:方法重载只比较参数,即只比较参数的个数和类型。对于参数的名字和方法返回类型不予考虑。整数默认是int,小数默认是double:例如:public static void main(String[] args) {System.out.println(fun(12.0,13.0)); //由于默认小数是double,所以调用double方法}public static boolean fun(double a, double b){System.out.println("double");return a == b;}public static boolean fun(float a, float b){System.out.println("float");return a == b;}如果想要调用float方法,要么在小数前加转化类型,要么在小数后加f如果方法的参数是基本数据类型:则方法对变量的操作不影响实参例如: change(a,b) //a还是a,b还是b,不会交换
18-11-8:方法参数是引用类型、断点调试、面向对象格式、初始化值问题、内存分配(重点).txt****
·如果方法的参数的类型引用型参数,方法会影响该引用型变量
public static void main(String[] args) {int[] arr = {1,2,3,4,5};change(arr); //将arr作为参数传进去for(int i = 0; i < arr.length; i++){System.out.println(arr[i]); //此时数组的元素全部乘了2}}public static void change(int[] a){for(int i = 0; i < a.length; i++){a[i] *= 2;}}
·断点
基本操作和Dev C++ 一样
·面向对象:
类中的方法定义:public int fun(..) // 去掉主类中的static类中的属性可以不用设值,原因请参考"初始化值的问题"
.初始化值的问题:
在java中数组在定义时每个元素有初始化值;构建类时,每个属性也有初始化值;除了数组和类以外,其他所定义的任何变量都没有初始化值。例如:int i;String s;syso(i);syso(s); //都是The local variable 变量名 may not have been initialized原因分析:如果定义一个基本数据类型,它们是放在栈中,值也保存在栈中,没有赋予初始值,要使用前必须赋值。而数组和对象是new出来的,它们保存在堆中,堆内存一开始就为它们赋予了初始值
JAVA变量内存分配:
方法区:javac编译后的 字节码文件 都放在 方法区 中,每个字节码文件就是一个类(这也是为什么类名要和文件名一致)。方法 和 属性 也在方法区中的 字节码文件 。栈:当 调用某方法 时就会将方法 加载到栈 中,方法中的变量也会加载到栈中。如果这些变量是 基本数据类型,其值和变量一起放在栈中。而且变量 没有初始值 。如果是 引用类型,其引用变量和其对象的 地址 也一起放在栈中, 指向堆 中的具体对象。如果栈中的方法执行完,其分配的内存就自动被垃圾回收机制回收。堆:如果是new出来的引用数据,就放在堆中。堆中对象的属性一般是基本数据类型,且都有初值。堆中存储对象的方法只是 存储其在方法区的地址 。
18-12-10:多异常处理顺序、finally、IO流标准处理异常格式、异常分类、自定义异常(代码)、异常总结.txt****
多个异常的处理:
允许处理多个异常,平级异常次序不重要。有子父级关系的话:子异常一定放在父异常前面。(如果父异常在前,那么就轮不到子异常处理,编译都通过不了)。
finally–不管try…catch处理异常是否成功,finally中一定执行。
例如:try {System.out.println(5 / 0);} catch(NullPointerException e) { //上面的异常无法捕获到。System.out.println("空指针"); } finally {System.out.println("释放资源");}结果:释放资源 //即使atch没有处理成功,但finally一定执行。Exception in thread "main" java.lang.ArithmeticException: / by zeroat com.异常处理.TryCatchDemo.main(TryCatchDemo.java:11)
IO流的异常处理格式(标准格式):
FileWriter fw = null; //将fw对象初始化,防止空指针异常,以后也一定写成这种样子。try {fw = new FileWriter(");fw.write("aaaaa");} catch (IOException e) {System.out.println("出现IO流异常");} catch (Exception e) {System.out.println("出现其他异常");} finally { try {if(fw != null) { //fw非空才将其关闭。fw.close();} } catch (Exception e) {System.out.println("关闭时发生异常");}}
异常的分类:
运行时期异常:可以不处理,且一定是java.lang.RuntimeException的子类。编译时期异常:写完必须处理,否则系统不准运行。非java.lang.RuntimeException的子类。
throw 与 throws:
throw是一种制造异常的方式。throws是一种处理异常的方式,是无法处理异常然后抛出去给调用者处理的方式。
自定义异常:
定义编译异常:只要继承Exception,然后写好构造方法就可以了。定义运行异常:只要继承RunTimeException然后写好构造方法就可以了。
自定义异常的例子(定义一个编译时期异常):
MyException.java
能够产生异常对象的类
public class MyException extends Exception {
各种构造方法...
}
Demo.java
public class Demo {
public static void main(String[] args) {try {checkScore(111); //由于定义的是编译时期异常,要么处理,要么抛给虚拟机,总之一定要处理} catch (Exception e) {System.out.Message());}}//此方法用于决定是否生成异常对象。如果满足条件则抛出异常。public static void checkScore(int score) throws MyException { //由于可能会产生异常,所以一定要在方法后面加上抛出哪种异常的可能。if(score > 100 || score < 0) {throw new MyException("成绩异常"); //如果抛出异常代表着方法的结束}System.out.println("成绩正常"); //如果没有抛出,则方法会一直执行到这。}
}
结果: 成绩异常
总结:
1.不管atch处理异常是否成功,finally中一定执行。2.FileWriter fw = null; 以后声明对象时一定设置为null。3.如果抛出异常,其所在的方法名后一定要加上"throws 异常类型"!!这是为了告诉虚拟机此方法可能会抛出xx异常。4.如果抛出运行异常,可以不用在方法后面throws,但是最好加上!!5.如果一个方法throws 编译异常,不管该方法是否有无throw异常,调用此方法时一定要进行处理!一定要处理!6.方法中如果抛出了异常(throw),则该方法就结束了。7.父异常要后catch
18-12-12:File类的概述、构造方法、创建、删除、获取、修改、判断功能.txt****
File类的使用:
概述:File可创建一个指向文件或者文件夹路径的对象,并可以进行一系列操作。构造方法:(注意:该文件或者文件夹不一定存在)File(File parent, String child) parent是一个文件夹的file对象,child是文件名称 File(String pathname) 一个文件或者文件夹的绝对路径 File(String parent, String child) parent是文件夹路径,child是文件的名称 创建功能:boolean createNewFile()创建文件 boolean mkdir() 只能在已经存在的目录中创建创建文件夹。boolean mkdirs() 可以在不存在的目录中创建文件夹。删除功能:boolean delete()可以删除文件或者文件夹,但如果文件夹下有子文件或子文件夹,则无法删除。(安全起见)判断功能:boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。 boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。 boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。 boolean exists() 测试此抽象路径名表示的文件或目录是否存在。 boolean isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件。 获取和修改功能:File getAbsoluteFile() 返回此抽象路径名的绝对路径名形式。 String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。 String getName() 返回由此抽象路径名表示的文件或目录的名称。 String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。 File getParentFile() 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。 String getPath() 将此抽象路径名转换为一个路径名字符串。 boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。 String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。 File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
18-12-13:IO流分类、用字节流进行图片复制、提一下标准输入出流、以后采用数组复制方式.txt****
IO流高级:
IO流分类(按数据类型):字节流:字节输入流: InputStream字节输出流: OutputStream字符流:字符输入流: Reader字符输出流: Writer
用字节流复制图片:
public static void Chars() throws FileNotFoundException, IOException {//创建对象FileInputStream fis = new FileInputStream("C:\Users\熊汝成\Pictures\Saved Pictures\timg .jpg");FileOutputStream fos = new FileOutputStream("裴秀智.jpg");byte[] bs = new byte[1024];int len;while ((len = ad(bs)) != -1) {fos.write(bs, 0, len); }fis.close();fos.close();System.out.println("成功");}注意点:1.字节流不需要flush,字符流才需要flush。2.以后用数组方式进行复制,高效。
标准输入输出流:
System.in 标准输入流:用于录下键盘中输入的数据System.out 标准输出流:用在在终端中输出数据
18-12-16:isr与osw的介绍、字符流的操作,字节流的功能.txt****
1.OutputStreamWriter的引用–问题:将数据输出到终端
//输入流对象建立BufferedReader br = new BufferedReader(new FileReader("));//标准输出流对象的建立OutputStream os = System.out; //多态String line;while ((line = br.readLine()) != null) {os.Bytes()); //必须将字符串转化成字节流数组才可以os.write("n".getBytes());}br.close();os.close();从上可以看出,当使用OutputStream写入必须是字节或字节数组,现在不想将字符串传换成字节数组。引入OSW------------------------------------------------------------------------------------改进源码//输入流对象建立BufferedReader br = new BufferedReader(new FileReader("));//标准输出流对象的建立OutputStreamWriter osw = new OutputStreamWriter(System.out); String line;while ((line = br.readLine()) != null) {osw.write(line); //像字符流一样的操作了osw.write("n");}br.close();osw.close();
2.终端写入数据:
InputStream is = System.in;FileWriter fw = new FileWriter(");byte[] bs = new byte[1024];int len;while ((len = is.read(bs)) != -1) { //is只能读字节数组fw.write(new String(bs,0,len)); //把字节数组转化成字符串fw.flush();}is.close();fw.close();-----------------------------------------改进:InputStream is = System.in;InputStreamReader isr = new InputStreamReader(is);FileWriter fw = new FileWriter(");char[] chs = new char[1024];int len;while ((len = ad(chs)) != -1) {fw.write(chs,0,len);fw.flush();}is.close();fw.close();
总结:
InputStreamReader和OutputStreamWriter还是字符流,是包装了字节流的字符流!他们构造方法中传入字节流对象,然后操作上就是字符流的操作。这样做到了"字节流的功能,字符流的操作"
18-12-18:字符打印流的概述.txt****
打印流PrintWriter:
概述:同FileWriter一样,也可以对文件进行写入字符流数据。复制文本:BufferedReader br = new BufferedReader(new FileReader("));//pw的构造方法很多,此构造方法是为了打开自动刷新的功能PrintWriter pw = new PrintWriter(new FileWriter("D:\"), true); String line; while ((line = br.readLine()) != null) {pw.println(line);}/** 即使没有刷新,没有关闭文件,同样也能进行自动刷新和换行。*/
18-12-18:对象操作流的使用.txt****
对象操作流:
概述:可以将对象输入到文件当中。ObjectInputStream:构造方法:传入一个InputSteam及其子类的对象。读取对象的方法adObject() 抛出编译异常ClassNotFoundException(如果这个对象的类找不到了)读取文本对象的方法:方法一:如果文件中全是对象try {while (true) {Object o = adObject();System.out.println(o);}} catch (EOFException e) {System.out.println("文件读完");}方法二:如果文件中是一个集合ArrayList<Student> list = (ArrayList<Student>) adObject();for (Student student : list) {System.out.println(student);}ObjectOutputStream:构造方法:传入一个OutputSteam及其子类的对象。写入对象的方法:oos.wirte()注意:1.构造方法一定是传入一个字节输入流或者字节输出流。2.写入的对象一定要实现Serializable这个接口。
18-12-19:IO流的大总结.txt****
IO流的总结:
File:是指向文件或者文件夹路径的一个对象。知识点:构造方法、创建、删除、获取、判断、修改等功能。
FileInputStream、FileOutputStream:对文件的读写(以字节为单位)知识点:构造方法:传入File对象或者String(传入String其实是自动创建File对象) 主要方法:int read()---返回数字。int read(byte[] b)---将字节流存到byte数组中。void write(byte[] b, int off, int len) ---将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 void write(int b)--- 将指定字节写入此文件输出流。 注意要点:不管是读还是写,都是以字节byte为单位。写入数据不需要flush刷新。
FileReader、FileWriter:对文件的读写(以字符为单位)注意要点: 大部分知识点和fis、fos一样。写可以写入各种数据类型(String、int、),但读写都是以char为基本单位。写入数据需要flush刷新。
InputStreamReader、OutputStreamWriter:字节流的功能字符流的操作知识点: 构造方法:传入InputStream、OutputStream子类的对象。注意要点: 该类的方法同Reader、Writer的操作是一样的。它是将字节流的能力包装成字符流的操作。
PrintWriter:打印流知识点: 构造方法: 传入File、Writer、OutputStream都可以注意要点: 其实同FileWriter类似,不过他有自动刷新和自动换行的功能。
BufferedWriter、BufferedReader:缓冲流 知识点: 构造方法:传入Reader、Writer对象。注意要点: 能够更加高效的处理字符流。可以读取一行和独特的换行功能。
ObjectInputStream、ObjectOutputStream:对象操作流 知识点: 构造方法: 传入InputStream、OutputStream对象 主要方法: readObject() 抛出编译异常ClassNotFoundException ,读完所有对象会抛出EOFExceptionwriteObject() 写入对象注意要点: 加入的对象的类必须实现接口Serializable
总而言之:
1.fis,fos,fw,fr的构造方法都是传入File对象。主要方法是read和write,写的单位是byte和char。字节不刷新字符要刷新。2.br和bw把fr与fw包装进去,能够提供高效。newLine和readLine是独特方法。3.对象操作流的构造方法是传入字节流(一般是FileInputStream和FileOutputStream),加入的对象一定要实现接口。读对象可能
找不到类所以抛出一个编译异常,读完文件会抛出一个运行异常。
18-12-20:Properties与IO流的结合.txt****
Properties与IO流的结合: 有种专门的文件是 xxx.properties
Properties的概述:类似于Map,但键值对只能是String。被称为属性列表。基本功能:存数据:setProperty(String key, String value) 拿数据:getProperty(String key) 遍历数据:Set<String> stringPropertyNames() 可以获取所有的键集源码演示://创建Properties对象Properties pro = new Properties();//存入数据pro.setProperty("001", "xrc");pro.setProperty("002", "lw");//遍历Set<String> keys = pro.stringPropertyNames(); //获取到了所有的键。for (String key : keys) {String value = Property(key);System.out.println(key + "=" + value);}-------------------------------------------------------------------------------------------------与IO流的结合:具体方法:写出数据:void store(OutputStream out, String comments) void store(Writer writer, String comments) 读入数据:void load(InputStream inStream) void load(Reader reader) 源码演示: /** 将属性列表放入到文件当中**///创建属性列表对象 Properties prop = new Properties();//创建输出流对象FileWriter fw = new FileWriter(new File("学生"));//添加键值对关系prop.setProperty("001", "熊汝成");prop.setProperty("002", "刘威");prop.setProperty("003", "周玄");//将关系存放到文件当中prop.store(fw, "存放学生对象");//释放资源fw.close();===========================================/** 将文件中的关系读入到属性列表中*///创建一个空的属性列表Properties prop = new Properties();//创建输入流对象FileReader fr = new FileReader(new File("学生"));//从文件中读取数据prop.load(fr);//释放资源fr.close();//遍历属性列表,看是否加载成功Set<String> keys = prop.stringPropertyNames();for (String key : keys) {String value = Property(key);System.out.println(key+"="+value);}
18-12-20:关于固定序列化ID的必要性.txt****
关于序列化接口ID的问题:
存入一个学生对象后,对学生类进行了修改。在进行读入的时候,就会抛出java.io.InvalidClassException异常。原因:将学生类写好并实现序列化接口后则系统会分配一个默认的序列化ID,且每次对学生类进行修改后则序列化ID会改变。当进行读学生操作的时候,发现读的学生类型的序列化ID和现有学生类型的序列化ID不同时,则抛出异常。措施:在学生类写好并实现了序列化接口以后,则立马固定住序列化ID,这样无论怎么修改,ID不变。就不会抛出错误。直接在Student类中写一个成员变量 private static final long serialVersionUID = 8846915965544563304L;
18-12-22:Map和List都实现了序列化接口、关闭最外层stream或er便可。.txt****
1.JAVA中的Map、List都是实现了序列化接口,都可以将其存到文件当中。
2.JAVA的IO包下的stream和er都是装饰者模式,只需要调用最外层的close方法就能将内部的stream或er一并关闭。
18-12-26:多线程的概述、多线程的第一种实现方式.txt****
多线程的概述:
进程:可以理解为一个程序。单线程:一个进程中只做一件事情。安全,效率低。多线程:一个进程中做多个事情。不安全,效率高。
执行多线程的步骤:
1.创建类并继承Thread 2.将要执行的代码放在void run()中。3.在主方法中创建对象。4.调用对象的start方法,该方法会自动执行run中的代码。代码如下:主类:public class ThreadDemo {public static void main(String[] args) {MyThread mt = new MyThread();HerThread ht = new HerThread();mt.start();ht.start();}}---------------------------------------------------线程类:public class MyThread extends Thread {public MyThread(){setName("熊汝成");}@Overridepublic void run() {for (int i = 1; i < 3 ; i++) {System.out.println("这是"+getName()+"的第"+i+"个线程!");}}}class HerThread extends Thread {public HerThread() {setName("李育霖");}@Overridepublic void run() {for (int i = 1; i < 3; i++) {System.out.println("这是"+getName()+"的第"+i+"个线程!");}}}结果:不唯一。这是李育霖的第1个线程!这是熊汝成的第1个线程!这是熊汝成的第2个线程!这是李育霖的第2个线程!
18-12-26:有关异常中空指针问题、学生管理系统中常出现EOF解决.txt****
关于JAVA的try中的问题:
try {FileReader fr = new FileReader(");} catch (FileNotFoundException e) {System.out.println("没有此文件");}fr.close(); //此时fr会亮红线
Java严格讲究代码块的域,出了域绝对找不到变量。fr是一个放在try的代码块中,fr.close()自然
找不到fr变量。修改方式:
FileReader fr = null;try {fr = new FileReader(");} catch (FileNotFoundException e) {System.out.println("没有此文件");}fr.close(); //但会抛出运行异常java.lang.NullPointerException
fr首先是个null,try中的赋值语句没有成功,所以fr一直是null,修改:
FileReader fr = null;try {fr = new FileReader(");} catch (FileNotFoundException e) {System.out.println("没有此文件");}if (fr != null){fr.close();} //这样才是正确的方式。
在写学生管理系统的时候,如果"学生.txt"是一个空文件,在构造ObjectInputStream对象时就会报EOF异常。
看看我是如何排错的:
ObjectInputStream ois = null; //先设立为nulltry {ois = new ObjectInputStream(new FileInputStream("学生")); //尝试下创立ois对象} catch (EOFException e) {HashMap<String, Student> map = new HashMap<String, Student>(); //如果报错就添加一个空map进去ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("学生"));oos.writeObject(map);oos.close(); ois = new ObjectInputStream(new FileInputStream("学生")); //再创立一次ois对象}
18-12-2:容器中元素的遍历(转化数组、迭代器)、迭代器中的并发异常、修改迭代器中的元素也会修改原容器中的元素.txt****
元素的遍历:
方法一:转化成object数组,再进行遍历。//方法一,转化成数组进行遍历Collection c = new ArrayList();c.add("hello");c.add("java");c.add("xiongrucheng");Object[] os = c.toArray();for(int i = 0; i < os.length; i++){System.out.println(os[i]);}方法二:转化成迭代器对象,进行遍历:Collection c = new ArrayList();c.add("hello");c.add("java");c.add("xiongrucheng");Iterator it = c.iterator();while(it.hasNext()){System.out.());}
解决迭代器中的并发异常:
由于迭代器是集合的副本,必须与集合相一致。如果迭代器中的元素没有变,但集合中的元素发生改变就会造成:Exception in thread "main" java.util.ConcurrentModificationException(并发修改异常)如果集合中的元素没有变,修改迭代器,迭代器会影响集合的变化。//声明一个List对象List list = new ArrayList();//添加三个元素list.add("hello");list.add("java");list.add("xiongrucheng");//调用list.listIterator() 制造一个列表迭代器,因为列表迭代器拥有add方法ListIterator itor = list.listIterator();System.out.println(list); //结果:[hello, java, xiongrucheng]while(itor.hasNext()){String s = ((); //()转化一个String对象,向下转型if(s.equals("java")){itor.add("python"); //注意,如果是list.add("python")会引发异常,所以是迭代器中添加元素}}System.out.println(list); //[hello, java, python, xiongrucheng] //迭代器的变化造成了原集合的变化
迭代器可以对原集合进行永久改变:
LinkedList<Student> list = new LinkedList<Student>();//添加元素list.add(new Student("熊汝成", 19));list.add(new Student("刘威", 18));list.add(new Student("李凯文", 20));//通过迭代器进行修改,通过迭代器,将每一个元素的名字和年龄修改Iterator<Student> itor = list.iterator();while(itor.hasNext()){Student s = ();s.setAge(0);s.setName("无名氏");}//在进行遍历原列表for (Student student : list) {System.out.println(student);}结果:Student [name=无名氏, age=0]Student [name=无名氏, age=0]Student [name=无名氏, age=0] //发现利用迭代器进行操作了以后,原集合也都改变了。
18-12-2:泛型和增强for循环.txt****
泛型:
在java的集合类中,有许许多多的泛型。因为集合可以添加任何类型元素,泛型可以将集合像数组一样,规定添加元素的类型。
增强for循环:
for(ElemType e : 集合对象){}
18-12-3:List中的增删查改、元素是对象时的排序(附加源码)、foreach的修改元素.txt****
List对象中的操作:
初始化: List<Student> mylist = new LinkedList<Student>();//其实增删查改同ArrayList一样。添加:mylist.add();删除ve();查找()修改:mylist.set()排序:Collections.sort(列表)注意:1.列表中的元素的类型(比如Student),一定要实现Compareble,且重写 int compareTo(E o)方法。2.返回值是一个整形,是自己的属性与对方的属性的差值。
对于ArrayList,上述也是如此。
具体用ArrayList还是LinkedList,取决于你是增删多,还是查改多。
foreach对于元素是基本数据类型的数组修改无效,对于元素是引用类型的数组修改有效.
例如:for (Student student : list) {student.name = "hhh"; //list中的元素是引用数据类型,foreach修改成功}for(int i : intArray){i = 20; //intArray中的元素是int,foreach不可修改}
源码:
Demo.java
package com.sort_and_find;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Demo {
public static void main(String[] args) {List<Student> list = new LinkedList<Student>();//添加学生list.add(new Student(1709301, "zw", 108));list.add(new Student(1709305, "xrc", 19));list.add(new Student(1709302, "laowang", 50));//先输出学生for (Student student : list) {System.out.println(student.schoolnumber+"-"+student.name+"-"+student.age);}System.out.println("------------");//排序Collections.sort(list);//再输出,利用迭代器Iterator<Student> itor = list.iterator(); //注意,迭代器也要指定泛型while(itor.hasNext()){Student student = ();System.out.println(student.schoolnumber+"-"+student.name+"-"+student.age);}//利用二分法来查找/** 利用二分法,首先要排好序* 其次,查找是根据Student中compareTo方法比较的何种属性进行查找的*/int index = Collections.binarySearch(list, new Student(1709302,"laowang",108));System.out.println(index);}
}
Student.java
package com.sort_and_find;
public class Student implements Comparable{
int schoolnumber;String name;int age;public Student() {super();// TODO Auto-generated constructor stub}public Student(int schoolnumber, String name, int age) {super();this.schoolnumber = schoolnumber;this.name = name;this.age = age;}@Overridepublic int compareTo(Student o) {// TODO Auto-generated method stubreturn this.age - o.age; //根据年龄比较}
}
结果:
1709301-zw-108
1709305-xrc-19
1709302-laowang-50
1709305-xrc-19
1709302-laowang-50
1709301-zw-108 //根据年龄排序
2 //只能根据年龄进行查找
18-12-4:collections工具类中对容器的洗牌与旋转.txt****
洗牌与旋转:
Collections提供了以下方法:洗牌:public static void shuffle(List<E>list) 可以将数据重新排列。旋转:public static void rotate(List<E>list, int distance)逆转:public static void reverse(List<E> list)
18-12-4:有关HashMap的相关操作,特别是遍历.txt****
散列映射(字典)的基本操作:
1.初始化:HashMap<String, Student> map = new HashMap<String, Student>();2.添加元素:map.put("xiongrucheng", new Student("熊汝成", 19));3.输出map中的元素个数syso(map.size())4.根据键来查询元素Student s = ("xiongrucheng");System.out.println(s); //结果:Student [name=熊汝成, age=19]5.查询是否包含该键:System.out.ainsKey("xiongrucheng")); //结果:true6查询是否包含该值:System.out.ainsValue(new Student("威威", 50))); //结果,false,因为两对象地址不同7.移除ve("likaiwen");8.遍历://map.values()将返回一个实现了Collection<Student>接口类创建的对象。个人理解应该是返回了一个实现了Collection的//匿名内部类的对象。并将该对象赋值给接口变量。Collection<Student> c = map.values();//c因为实现了接口的方法,所以可以返回一个确确实实的迭代器。Iterator<Student> itor = c.iterator();//遍历迭代器while(itor.hasNext()){System.out.());}//当然,也可以用foreach来遍历这个对象Collection<Student> values = map.values();for (Student student : values) {System.out.println(student);}9.清空:map.clear(); 10.键值对的遍历:上面的8是对键或者对值的单独遍历,现在讨论键值对的遍历方法一:public static void Method1(Map<String, String> map) {//通过对键的遍历,一个个的遍历MapSet<String> keys = map.keySet();for (String key : keys) {String value = (key);System.out.println(key + "--" + value);}}方法二://利用Map中的内部类进行遍历public static void Method2(Map<String, String> map) {Set<Map.Entry<String,String>> entrys = Set(); //Map.Entry是Map中的内部类for (Map.Entry<String, String> entry : entrys) { System.out.Key()+"--"Value());}}注意点:如何通过键进行对值的修改?只需要重新put()就可以进行覆盖修改了
18-12-4:栈的基本操作.txt****
栈堆:
boolean empty() 测试堆栈是否为空。 E peek() 查看堆栈顶部的对象,但不从堆栈中移除它。 E pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。 E push(E item) 把项压入堆栈顶部。 int search(Object o) 返回对象在堆栈中的位置,以 1 为基数。
18-12-5:List中的排序(详解),Comparable与Comparator的区别(内外比较器的比较)、学生集合各个属性排序(完整代码).txt****
List中的排序问题:
1.对于基本数据类型:正序Collections.sort(list);逆序Collections.sort(list,new Comparator<Integer>(){ //实现一个Comparator的内部类对象public int compare(Integer o1, Integer o2) {return o2 - o1;}});2.对于引用数据类型的排序:方法一:利用匿名类实现Comparator<Student>接口Collections.sort(list,new Comparator<Student>(){@Overridepublic int compare(Student o1, Student o2) {Rank() - o2.getRank(); //根据名字排序:Name()Name());} });方法二:Student类中实现Comparable<Student>接口类:public class Student implements Comparable<Student>{...}重写方法:@Overridepublic int compareTo(Student o) {return o.rank - this.rank;}
Comparable 与 Comparator的区别:
内比较器:Comparable形容词,表示可比较的。这种接口往往是需要类去实现的,从而增加类的一个“可比较”功能。外比较器:Comparator表示比较器,一般是通过内部类实现该接口的功能,用于给Collections.sort()传递参数。一般推荐这种方式。
对学生的各个属性排序的完整代码:
package com.sort_and_find;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SuperDataDemo{
/**静态的成员内部类*/static class sortByName implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {Name()Name());}}static class sortByAge implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {Age() - o2.getAge();}}static class sortByRank implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {Rank() - o2.getRank();}}public static void main(String[] args) {List<Student> list = new ArrayList<Student>();//添加学生list.add(new Student("jack", 45, 'a'));list.add(new Student("beak", 20, 'c'));list.add(new Student("tom", 90, 'f'));list.add(new Student("keven", 31, 't'));list.add(new Student("anny", 8, 'e'));//遍历for (Student student : list) {System.out.print(student);}System.out.println();//排序,根据xx来排序Collections.sort(list, new sortByRank());//遍历for (Student student : list) {System.out.print(student);}System.out.println();}
}
18-12-9:异常的处理、抛出(初步,后续还有补充).txt****
异常处理:
1.异常体系:超类:java.lang.Throwable--->java.lang.Error(不可扭转的的错误), java.lang.Exception(可处理的异常)2.异常处理的方式:捕获并处理异常抛出异常3.捕获并处理异常atch语句:格式:try{可能发生异常的语句} catch(异常类型 e){处理语句}注意点:1.发生异常后,如果没有atch语句,则jvm会自动关闭程序。2.如果写了语句,发生异常后自动跳转到catch中,不会再跳回try语句中。例如:代码:try{System.out.println("try的第一条");System.out.println(4/ 0);System.out.println("try的第二条"); //跳转到catch中,不会再回来} catch(Exception e){System.out.println("发生异常");}结果:try的第一条发生异常4.抛出异常:异常都是发生在某个方法当中,如果没能力处理或者不想处理该异常,就可以将异常抛出去,交给调用方法的人去处理。格式:方法名() throws 异常类型{} //注意,异常类型可以写此异常类型的父类型。
抛出异常还遗留许多问题,见后续补充
19-1-10:TCP通信的补充点.txt****
TCP协议进行数据通信的注意点:
1.输入流--------------相互连接--------------输出流| | | || |客户端Socket 服务端Socket | || || | 输出流--------------相互连接---------------输入流如图所示,客户端的Socket与服务端accept后的Socket的交错连接。调用getInetAddress()方法获取的是对方的IP对象。2.Java的socket是一个全双工套接字,任何的输入流或输出流的close()都会造成Socket关闭。所以,不要用close方法关闭socket的IO流,可以用shutdown方法。
19-1-13:单元测试****
Junit单元测试:
在主类中的方法中添加注解@Test、@After、@Before便可进行单元测试,且方法不可是静态方法。
19-1-5:InetAddress类的简要了解.txt****
InetAddress类的介绍:
概述:此类表示互联网协议 (IP) 地址。初始化方法:static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。 host可以是主机名,也可以是ip地址。获取方法:String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。 String getHostName() 获取此 IP 地址的主机名。 static InetAddress getLocalHost() 返回本地主机。
19-1-5:主方法的运行是单线程的、多线程的第二种实现方法.txt****
主方法是单线程的,在主方法中调用各种方法时,程序是从上往下,从左往右运行。
实现多线程的第二种方式:
1.创建一个类实现接口Runnable,并重写run方法。2.在主方法创建类实例mt。3.在主方法中创建Thread实例t,并将mt对象传递进去。4.调用start方法,开启线程.代码如下:主类:public class ThreadDemo {public static void main(String[] args) {//创建MyThread对象MyThread mt = new MyThread();//创建第一个Thread对象,将mt传进去。Thread t = new Thread(mt);t.setName("老王");//创建第二个Thread对象,将mt传进去Thread t2 = new Thread(mt);t2.setName("老张");t.start();t2.start();}}自定义类:public class MyThread implements Runnable {@Overridepublic void run() {for (int i = 1; i < 4; i++) {System.out.println(Thread.currentThread().getName() + //静态的获取当前线程的方法"的" + i + "个线程");}}运行结果:老张的1个线程老王的1个线程老王的2个线程老王的3个线程老张的2个线程老张的3个线程第二种方法的意义:第一种方法是继承,第二种方法是实现,二解决了一的多继承问题。
19-1-5:利用同步代码块或同步方法解决多线程中的并发问题.txt****
多线程可能遇到的问题:
当有多个线程。多个线程共享一个数据源。就有可能会造成数据重复执行等问题。为了解决这个问题,引进同步代码块的概念。
同步代码块:
格式:synchronized (this) {每一个线程的运行代码。}作用:当线程的运行代码被synchronized(this){}包住以后,当运行这个线程时,将会开启一个锁,其他线程暂时无法运行。
源码:
public class MyThread implements Runnable {
int count = 100; //票的总数@Overridepublic void run() {while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (this) { //需要进行封锁的地方,加上同步代码块if (unt > 0) {System.out.println(Thread.currentThread().getName() + "第" + unt + "张票正在出售");unt --;}}}}
}
public class ThreadDemo {
public static void main(String[] args) {//实例化mt对象.MyThread mt = new MyThread();//实例化多线程窗口一Thread t1 = new Thread(mt);t1.setName("窗口一");//实例化多线程窗口二Thread t2 = new Thread(mt);t2.setName("窗口二");//实例化多线程窗口三Thread t3 = new Thread(mt);t3.setName("窗口三");//实例化多线程窗口四Thread t4 = new Thread(mt);t4.setName("窗口四");//启动线程t1.start();t2.start();t3.start();t4.start();}
}
同步方法:
将synchronized放在run方法前面作为修饰符修饰,就可以将整个方法锁住。@Overridepublic synchronized void run() { ... } //用synchronized修饰后也是重写方法。
19-1-6:利用UDP协议发送并接收数据.txt****
使用UDP协议发送数据:
步骤:1.创建发送端对象DatagramSocket类的对象。2.创建数据包对象DatagramPacket类的对象,包含了数据,ip地址,端口号。3.发送出去。4.释放资源创建发送端对象DatagramSocket类的对象:使用无参构造,因为发送端不关心端口号。DatagramSocket ds = new DatagramSocket();创建数据包对象DatagramPacket类的对象,包含了数据,ip地址,端口号。DatagramPacket dp = new DatagramPacket(bys, length, address, port); 发送数据:ds.send(dp);
发送端完整程序:
public class UDPSendDemo {
public static void main(String[] args) throws IOException {//1.创建发送端对象DatagramSocket类的对象。DatagramSocket ds = new DatagramSocket();//2.创建数据包对象DatagramPacket类的对象,包含了数据,ip地址,端口号。String content = "你好,我叫熊汝成";byte[] bys = Bytes(); //将字符串转化成字节数组int length = bys.length;InetAddress address = ByName("192.168.190.1"); //创建InetAddress对象。int port = 8888;DatagramPacket dp = new DatagramPacket(bys, length, address, port);//3.发送出去。ds.send(dp);//4.释放资源ds.close();}
}
UDP协议接收数据:
步骤: 1.创建DatagramSocket对象2.创建Datagrampacket对象,这是一个容器,接收数据要用到3.接收数据,将数据放在包中。4.解包,获取包中的各项数据5.释放资源创建DatagramSocket对象:注意,要与发送端的端口号一致。DatagramSocket ds = new DatagramSocket(8888);创建Datagrampacket:使用DatagramPacket(byte[] buf, int length)构造便可,因为只是为了接收数据,创建一个容器便可。接收数据,将数据放在包中ive(dp); //这样就将数据放在了容器dp中。解包,获取包中的各项数据:通过dp中的各种get方法得到数据。
完整程序:
public class UDPGetDemo {
public static void main(String[] args) throws IOException {//1.创建DatagramSocket对象DatagramSocket ds = new DatagramSocket(8888);//2.创建Datagrampacket对象,这是一个容器,接收数据要用到DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);//3.接收数据,将数据放在包中。System.out.println("准备接收数据");ds.receive(dp); System.out.println("接收到了数据");//4.解包,获取包中的各项数据byte[] bys = dp.getData();InetAddress address = dp.getAddress();int length = dp.getLength();String content = new String(bys, 0, length);System.out.println("sender -->" + HostName());System.out.println("content -->" + content);//5.释放资源ds.close();}
}
注意:在第75行会有发生堵塞,打开接收端后程序会一直运行,直到收到消息。
19-1-9:利用TCP协议进行数据的发送和接收.txt****
利用TCP协议进行发送数据:
步骤:1.创建Socket对象2.从Socket对象中获取输出流对象。3.利用输出流发送数据4.释放资源创建Socket对象:Socket(InetAddress address, int port) //对方的IP地址和端口号从Socket对象中获取输出流对象:OutputStream os = s.getOutputStream();利用输出流发送数据:os.write(byte[]);
利用TCP协议进行接收数据:
步骤: 1.创建ServerSocket对象。2.利用此对象返回一个Socket对象,用于监听(堵塞)3.获取输入流对象4.获取数据5.释放资源创建ServerSocket对象:ServerSocket ss = new ServerSocket(9999); //本机端口号利用此对象返回一个Socket对象,用于监听(堵塞):Socket s = ss.accept(); //在此处程序堵塞获取输入流对象:InputStream is = s.getInputStream();获取数据:String sender = s.getInetAddress().getHostAddress() + "--" InetAddress().getHostName();byte[] bys = new byte[1024];int len;len = is.read(bys);String content = new String(bys, 0, len);System.out.println("sender -->" + sender);System.out.println("content -->" + content);释放资源:s.close();
// ss.close(); //服务端不应该关掉。
2019-1-13:JAVA的类加载机制.txt****
JAVA的类加载机制:
1.加载class文件到内存2.将加载好的数据融合到jre这个大的环境中。3.进行一系列初始化的工作
<****
18-11-11:同类不同对象的方法指向一个区、成员变量与局部变量、私有化、构造方法及其重载.txt****
两个对象所指向的方法是同一个地址:
如果有两个对象p1,p2,他们的方法其实都是放在方法区中。而他们的对于共同指向此方法
成员变量和局部变量区别:
位置:成员变量是在类中声明的局部变量是在方法体中或者形式参数中声明内存:成员变量是在堆中局部变量是在栈中 初始化值:成员变量因为是在堆中所以有初值局部变量在栈中,所以声明后必须要先赋值才能使用
private修饰符:
放置位置:放在变量或方法的最前面作用:被修饰后的变量或方法只可以在本类中使用,在外类不可见。这样可以保证数据安全配合:被private修饰了的变量一定要有对应的setXxx() 和 getXxx()公有方法
构造方法:
格式:public Student(...){ //与类名同名,且没有返回类型。}调用构造方法:Student s = new Student(..) //其实new后面的就是调用了一个类的构造方法构造方法的注意事项与重载:如果没有构造方法,则系统会自动提供一个无参数的构造方法。如果有了带参数的构造方法,无参构造方法就要自己构造。推荐只要写一个类,就要有一个无参构造方法
18-11-12:方法的形参和返回值可以是对象、API、==详解、String对象初步、直接赋值和new字符串对象区别.txt****
类中的方法的形式参数和返回值可以是一个对象:
形参-例如:public void UseStudent(Student s){System.out.println("我是个老师,现在调用学生的方法");s.speak();}返回值-例如:public Student getStudent(){ //返回类型是类,则返回对象Student s = new Student();return s;}
API的使用:
API就是帮助文档
==:
如果是基本数据类型则比较的是值是否相等。如果是引用数据类型则比较的是地址是否相等。
String对象初步:
String是个特殊的引用类型对象syso(str) //一般来说打印引用类型变量结果为其引用值,而打印字符串类型对象则直接打印结果new出的字符串对象和直接赋值的字符串对象的区别比较:new方式:new出来的依然是在堆内存,但是字符串的内容在方法区的常量池中。栈中的引用变量存了堆的地址,而堆中对象是存的常量池的地址。直接赋值:栈中的引用变量直接存的是常量池中的地址。常量池:字符串一般存在方法区当中的常量池中,同一个字符串在常量池中的位置唯一举例1:String s1 = "hello";String s2 = new String("hello");System.out.println(s1==s2); //false原因分析:s1存的是常量池当中的002;s2存的是堆中的001,堆中的001在存的是常量池中的002;001 != 002 所以false举例2:String s1 = "hello";String s2 = "hello";System.out.println(s1 == s2); //true原因分析: s1和s2存的都是常量池中的002,所以相等。注意: 因为字符串对象也是引用数据,所以在进行==比较的是地址的值。如果要比较字符串的值是否相等,则用s1.equals(s2)
//明天内容
String中的成员方法:
一:判断s1.equals(s2)s1.equalsIgnoreCase(s3) //忽略大小写
18-11-13:字符串的方法、主类中的方法注意事项提醒、next与nextLine区别.txt****
String对象的判断方法:
s1.equals(s2)s1.equalsIgnoreCase(s2) //忽略大小写s1.endsWith("lo")s1.startWith("he") //判断开头和结尾字符串
String的获取方法:
s.length() //注意,对于数组来说是a.lengths.charAt(1) //根据所以获取字符,返回的是单个字符s.substring(0, 5) //从0到4,截取字符串 左闭右开字符串的遍历:for(int i = 0; i < s.length(); i++){System.out.println(s.charAt(i));}
String的转化功能:
转化成字符数组:char[] chs = s.toCharArray();System.out.println(chs); //字符数组打印的是一个值,有别于其他数组,其他数组打印的是引用地址值。for(int i = 0; i < chs.length; i++){System.out.println(chs[i]);} 转化成字符串小写LowerCase()转化成字符串大写UpperCase()
String的其他操作:
关于主类中的方法注意事项:
测试类(主类)中的方法一定要写成public static 类型 方法名(..){}而类中的方法一定要写成public 类型 方法名(..){}
关于与Line方法区别:
注意,不管怎么输入,回车是指输入完毕!next只节选空格前的内容nextLine是节选输入的一行的内容
18-11-14:StringBuilder的构造方法、添加与反转、链式编程、与字符串的相互转化.txt****
StringBuilder与String的区别:
为什么要有StringBuilder?:因为每一次的字符串拼接都会浪费时间和存储空间,造成内存垃圾。而StringBuilder是一个可变的字符串对象,合理的解决了这个问题。
StringBuilder构造方法及其容量和长度:
StringBuilder sb = new StringBuilder(); //默认构造方法,长度为16sb.length() // 此字符串的字符个数sb.capicity() // 该对象的容量值,理论容量
StringBuilder的添加方法及其反转功能:
StringBuilder sb = new StringBuilder();//字符串的添加方法,链式编程。sb.append("hello").append("world").append(true).append(100); //append方法不管添加什么都可以,且sb对象直接可变。System.out.println(sb); //结果:helloworldtrue100//字符串的反转方法sb.reverse(); //reverse方法也是可以直接可变的。System.out.println(sb); //结果:001eurtdlrowolleh
StringBuilder 与 String的相互转化:
/** String 与 StringBuilder的相互转化:这样可以通用各自的方法*///String转化成StringBuilder:通过构造方法String s = "hello";StringBuilder sb = new StringBuilder(s);System.out.println(sb);//将StringBuilder转化成String:调用sb对象的toString方法StringBuilder sb2 = new StringBuilder("hahah");String s2 = String();System.out.println(s2);
18-11-16:ArrayList集合及其相关操作、缓冲流的问题提出.txt****
ArrayList:
缘由:因为此类是一个可以变化的数组,更加贴近实际应用。初始化:ArrayList<String> List = new ArrayList<String>(); //<>当中的是范型,这里以String举例。添加元素方法:boolean add(E e) 将指定的元素添加到此列表的尾部。 void add(int index, E element) 将指定的元素插入此列表中的指定位置。 打印:System.out.println(List); //结果:[C++, java, python, perl, php] 不同于其他引用类型变量,和String一样,直接打印值。长度、删除、修改、获取等方法:E set(int index, E element) //修改int size() //长度E get(int index) //获取E remove(int index) //删除boolean remove(Object o) //删除遍历:通过size方法和get方法对其进行遍历。for(int i = 0; i < List.size(); i++){String s = (i);System.out.println(s);}
为什么输入数字以后不能输入字符串?
输入数字以后会有个空白字符留在缓冲流之中,这个时候打一个 Line()就可以解决这个问题。具体内容以后再说。
18-11-16:StringBuilder的内容补充.txt****
利用StringBuilder 判断是否为对称字符的注意:
public static boolean isReverse(String s){StringBuilder sb = new StringBuilder(s);sb.reverse();return sb.equals(s); //sb和s是不同的对象,不管怎么样都返回是false。} //改成 String().equals(s) 就可以了
由于SB对象是一个可变的引用数据,故两个变量引用同一个对象时互相影响:
StringBuilder sb = new StringBuilder("abc"); StringBuilder s = sb; //s也指向sb的对象s.reverse(); //将s反转System.out.println(sb); //sb也被反转了。结果:cba
18-11-18:IO流fw和fr的使用、br和bw的使用、文本复制、nextInt后不能直接nextLine的解释.txt****
IO流
简述:
用于数据的读取和存储输入流:从文件中读取数据输出流:将数据存储在文件当中
FileWriter的基本使用:
public class IODemo {public static void main(String[] args) throws IOException {//创建fw对象,注意路径的格式是\FileWriter fw = new FileWriter("D:\1.txt");//写入内容fw.write("大家好我是熊汝成hahaha");//写入的内容还在内存缓冲区,需要进行刷 新才能将内容填入文件当中fw.flush();//关闭文件fw.close();}}
flush与close的区别:
flush是刷新内存缓冲区的内容,让其内容填入到文件当中close是先将进行flush的功能,在将文件关闭
追加与换行:
如果需要追加内容就是:FileWriter fw = new FileWriter(",true);如果需要换行:直接fw.write("n"); //windows的记事本无法显示,需要加一个rn
读取数据:
int ch; //fr.read返回int,是什么类型就用什么类型接收while((chad())!=-1){System.out.print((char)ch); //将int类型强制转化成char}
一次读取多内容数据:
FileReader fr = new FileReader(");char[] chs = new char[1024]; //默认定义为1024的整数倍int len;while((lenad(chs))!=-1){ //fr.read(chs) 将返回获取的内容的实际长度,-1表示没有内容了System.out.print(new String(chs,0,len)); //将字符数组转化成字符串}
复制文本内容-两种方式进行比较:
public static void copyBySoloChar(FileWriter fw,FileReader fr) throws IOException{ //单个字符int ch; //ch是每一个字符的编码值while((chad())!=-1){fw.write(ch);}}public static void copyByCharArray(FileWriter fw,FileReader fr) throws IOException{ //以字符数组char[] chs = new char[1024]; //获取的每一个字符放在数组中int len; //len是获取的实际长度while((lenad(chs))!=-1){fw.write(chs, 0, len); //将实际获取的文本写入到文件中}}
缓冲流:
相比于FileWriter与FileReader更加高效构造方法:BufferedWriter bw = new BufferedWriter(new FileWriter("));BufferedReader br = new BufferedReader(new FileReader(")); //构造方法里边的是fw或者fr对象
bw与br对象的特殊功能:
bw的特殊功能:for(int i = 0; i < 10; i++){bw.write(i+""); //将i转化成字符串bw.newLine(); //特殊的换行功能}br的特殊功能:String line;while((lineadLine())!=null){ //每次读取一行中换行符前面的内容System.out.println(line);}
利用特殊功能进行文本复制: //必须掌握
String line;while((lineadLine())!=null){bw.write(line);bw.newLine();}bw.close();br.close();
关于nextInt后面为什么不能用nextLine:
使用nextInt会将换行符前面的数字输入进去,而换行符留在了缓冲区。使用nextLine会将缓冲区中包括换行符在内的内容输入进去。由于nextInt后还有个n在缓冲区,当执行nextLine后就将n输入了进去,于是就造成了问题。改进:x = Int();Line(); //用于缓冲s = Line;
18-11-20:IO流的定位、static关键字、代码块.txt****
IO流的定位:
File file = new File("); //定义一个文件对象BufferedReader br = new BufferedReader(new FileReader(")); //构建一个缓冲输入流br.mark((int)file.length()+1); //先开始,光标指在文章的开头,现在在此处标记一下,参数是字符个数,如果光标输出字符数>=该值,则无法返回到标记处br.reset(); //让光标回到标记的位置
static关键字:
被static修饰的属性特点:被对象共享,一个对象的该属性变了,其他对象的该属性也跟着变了。可以直接由类名调用。注意事项:静态方法只能用静态的属性和方法。非静态方法什么都可以调。静态的方法里不可以有this关键字。原因:静态的方法和属性是随着类的加载而生成的,此时对象还没有出现,那些非静态属性和方法也没有生成。为什么主类中的方法都是静态的?:因为主方法是静态的,上面也提到静态方法只能调用静态的,所以主类中的方法也是静态的。静态的意义:如果将属性、方法都定义为静态的,将构造方法也私有(无法创造对象),此类就是一个工具类。由于不需要创造对象,靠类名就能直接调用。
代码块:
就是大括号,大括号里面的变量不能出去使用。构造代码块和静态代码块:主要是在创造类的对象时做的初始化工作,可能构造方法过多,所以将构造方法中同样的初始化方法放在代码块中例如:{System.out.println("老师对象创立成功"); //代码块,没创造一个对象就会调用}public Teacher(){System.out.println("我是无参");}public Teacher(String name, int age){System.out.println("我是有参");this.name = name;this.age = age;}结果: //类中代码块的执行早于构造方法,如果代码块换成static{},则"老师对象创立成功"只执行一次老师对象创立成功我是无参老师对象创立成功我是有参
18-11-21:继承的原因、继承中属性和方法的特点、方法重写注意事项、构造方法的继承问题.txt****
继承:
为什么要用到继承:如果很多个类有相同的部分,可以将相同的部分抽取出来变成一个父类。再让这些类继承于父类。java中继承的特点:只能单继承。可以多层继承继承中成员变量的特点:1:子类只能继承父类中的非私有属性,对于私有属性无法继承,但可以继承父类中的pulic getElement()方法,间接获取父类的私有属性。2:Father中有一个name,且Son中也有一个name,可让Son类通过super关键字访问父类中的name,也可以访问其他属性和方法,具体用法类似于this继承中成员方法的特点:1.子类只能继承父类中的非私有方法,对于私有方法无法继承2.如果子类中的方法和父类中的方法完全相同,这叫做方法重写。一般是父类的方法无法满足子类的需求,也可以通过super硬性调用父类方法方法重写的应用场景和注意事项:通过注解@Override可以得到以下的结论:1:方法重写的必须是父类中完全一样的方法!只是代码块中的东西可能不一样!2:继承的方法权限必须宽松或者等于父类中的方法权限。(一般权限相等)构造方法的继承:不管如何,在初始化子类前肯定会先初始化父类,因为子类可能要用到父类的初始化东西。(重点)子类中的构造方法如果没有写super和this关键字,则会默认调用父类的无参构造。如果想改变默认构造,可在子类构造方法中调用super(...)关键字
18-11-22:抽象类及其注意事项、final关键字、修饰符位置问题.txt****
抽象:
为什么要抽象:dog和cat都有eat方法,但eat不同的东西。如果直接继承Animal的eat无法满足,所以将Animal的eat方法抽象化,再让dog、cat去具体实现。abstract 关键字:修饰类和方法。一般放在public 的后面(当然放在public前面也没关系)例如:public abstract class Animal{}public abstract void eat();注意点:1.含抽象方法的类必定是抽象类,必须要用abstract去修饰类和方法。2.抽象类的子类要么完全实现父类的所有抽象方法,要么也定义为一个抽象类。3.抽象类中可以有非抽象方法。4.抽象类不可以实例化,即不可用抽象类来创建对象。抽象类中的成员特点:1.抽象类中可以有属性。2.抽象类中可以有抽象方法也可以有具体方法。3.抽象类虽然不能实例化但是也可以有构造方法。因为初始化子类前要初始化父类。4.抽象类不能是final类。因为final类没办法被继承,而abstract必须有子类实现。5.抽象类可以有常量(即final属性)
final:
1:被final修饰的属性是常量,最好一开始就赋值(也可以在构造方法中赋值)。一旦赋值不可再次修改。2:被final修饰的方法无法被子类重写。3:被final修饰的类无法被继承。
有关修饰符的位置问题:
public static abstract final 这几个修饰符的位置放置关系没有关系。但方法名的前面必须是返回类型便可。
抽象类也可以继承一个普通类。
18-11-25:多态、上下转型对象.txt****
多态:
概念:如果父类的引用指向了子类的实体,这时同种类型调用同种方法可能会出现不同的现象,这种现象叫多态。前提:1.有子父类。2.父类引用指向子类实体。上转型和下转型:上转型:父类引用指向子类对象。Father ob = new Son(); //称ob是new Son()的上转型对象。下转型:强制将上转型对象转化成子类对象。Son ob2 = (Son)ob; //将ob这个上转型对象强制转化成子类对象,并赋给子类对象ob2,这个时候ob2就是个正宗的Son对象了上转型对象的成员特点:1.成员变量:看左用左,父类必须有该变量,若子类有同名新变量,还是用的还是父类的成员变量。2.静态方法:看左用左,父类必须有该静态方法,若子类重写该方法,还是用的还是父类的该静态方法。3.成员方法:看左用右,父类必须有该方法,若子类重写该方法,用的是子类中重写后的方法!ps:看左是指父类中必须有这个玩意儿。否则无法通过编译器多态中的成员特点总结:调用成员方法和属性时父类必须要有该方法或属性,否则编译器无法通过。 (意思是不可调用子类新增)只有调用成员方法时是调用子类重写方法,其他的都是调用父类本有静态方法或属性。
18-11-25:接口、匿名对象.txt****
接口:
接口出现的原因:为了解决继承的单一性。有关接口的基本要点:1.接口是一个比抽象类还抽象的类,它的所有方法都是抽象方法。2.接口与类的关系不再是继承,而是实现。3.接口的定义格式就是将class换成interface。4.接口也可以用来申明变量。例如:Phone p; //其中Phone是一个接口,p一般是个上转型对象。接口的成员特点:1.对于成员属性,默认加上public static final修饰词,表示必须是一个可继承静态的常量。2.对于成员方法,默认加上public abstract 修饰词3.接口没有构造方法。4.同抽象类一样,如果实现接口时要么重写所有方法,要么也定义为一个抽象类。5.请将默认修饰符打出来。接口与类之间的关系:1.类与类:单继承。2.类与接口:多实现。3.接口与接口:多继承!4.一个类也可以同时继承和实现,不过要先继承后实现。 例如:class Final extends Student implements A {}
匿名对象:
没有变量引用:new Student() 这就是个匿名对象。应用场景:一般是一次性使用某个方法时用匿名对象。
18-11-26:权限修饰符、权限修饰符的使用规则.txt****
权限修饰符:
public 当前类中 当前包下不同类中 不同包下的不同类private 当前类中default 当前类中 当前包下不同类中protected 当前类中 当前包下不同类中
对于修饰符的场景使用:
1.一个java文件中只能有一个类,且该类是public类。2.所有的成员变量用private修饰。也要设置get、set方法。3.所有的方法都用public修饰。4.构造方法也都用public修饰,除非不想创建对象就用private修饰(工具类)。
18-11-27:Object中的toString、equals方法.txt****
Java高级API
1.String toString()方法:是Object中的方法,用于返回对象的地址。2.boolean equals(Object o) 是一个比较对象的地址值是否相等的方法。
18-11-27:内部类的使用.txt****
内部类:
成员内部类:1.成员内部类就是将内部类定义在外部类的成员位置当中。2.创建内部类对象前必须有外部类对象,所以定义格式是: Outer.Inner i = new Outer().new Inner();源码如下:public class MemberInnerClass {public static void main(String[] args) {Outer.Inner inner = new Outer().new Inner(); //创建内部类对象首先要有外部类对象inner.funInnerr(); }}class Outer{ //外部类 public void funOuter(){ //外部类的成员方法System.out.println("funOuter");}class Inner{ //内部类定义public void funInnerr(){ //内部类的成员方法System.out.println("funInner");}}3.修饰符:成员内部类可以直接用static修饰,这样就不需要外部类对象了。Outer.Inner inner = new Outer.Inner(); 局部内部类:1.局部内部类定义在外部类的方法体中。2.局部内部类所创建的对象也只能在外部类方法体中创建。3.局部内部类一般用的不多,只做了解内容源码如下: public class MemberInnerClass {public static void main(String[] args) {Outer o = new Outer();o.funOuter();}}class Outer{ //外部类public void funOuter(){class Inner{ //局部内部类的定义public void funInnerr(){System.out.println("funInner");}} Inner i = new Inner(); //局部内部类对象也只能定义在该方法之中。i.funInnerr();} }匿名内部类:1.格式: new 类/接口(){子类内容};2.代码块中是类的子类或者接口的实现类。3.功能与匿名对象相同,一次性调用。如果想多次调用,可以运用之前的向上转型对象原理。4.匿名内部类是同局部内部类一样必须放在方法体中。5.匿名内部类的应用场景是当一个对象作为参数传递一次时,为了不创建一个java文件,所以用匿名内部类对象。
18-11-28:Date类常用方法、SimpleDateFormat格式化日期.txt****
Date常用方法:
构造方法:1.Date d = new Date(); //默认获取当前系统时间2.Date d = new Date(long time) //将毫秒值传进去,设定指定时间对象常用方法:1. d.toString() //打印一个不友好时间2. d.toLocaleString() //打印一个友好时间,但已经过时3. d.setTime(long time) //设置时间4. d.getTime() // 获取时间毫秒
SimpleDateFormat日期格式化:
实例上演:public class DateDemo {public static void main(String[] args) {//按照指定模式创立的日期格式化对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E HH:mm:ss");//将Date日期传进去,就可以获取格式化当前时间字符串String s = sdf.format(new Date()); System.out.println(s); //结果:2018年11月28日星期三 17:31:48}}解析时间:Date d = sdf.parse("2018年10月28日星期三 17:31:48");System.out.LocaleString()); //结果:2018-10-28 17:31:48总结:sdf对象可以将Date对象的时间按指定格式化变成一个字符串(sdf.format()),也可以将指定格式化的字符串变成一个Date对象(sdf.parse()),它像一个中介,在Date对象 和 指定格式字符串 中相互转换。
18-11-29:Calendar类的基本使用.txt****
Calendar类的基本使用:
1.获取对象:Calendar c = Instance(); 2.获取时间:(Calendar.YEAR)) //Calendar.YEAR是一个字段,其实是该类的常量属性3.修改时间:c.set(int field, int value)4.增加时间:c.add(int field, int amount)
18-11-29:Collection接口概述.txt****
容器:
1.基本概念:可以装对象的东西。2.基本树:Collection(接口) --> Set(接口,无序不重复), List(接口,有序可重复) --> Map(接口,键值对存储)3.Collection接口中的基本方法:见API
18-11-29:包装类 Integer、字符串与整数的相互转换、自动装拆箱.txt****
包装类–Integer类的介绍:
核心内容是 int — String 的相互转化
int -> String:
方法1. number + "" // 最简单的方式方法2. Integer i = new Integer(10); //创立一个Integer对象,再调用对象的toString方法System.out.String() + 100); //10100方法3.String num_s = String(20) //调用该类的静态方法 public static String toString(int i) 。
String -> int:
方法1. Integer i = new Integer("100");syso(i + 400); //此时i就是一个int类型,结果为500(自动拆箱)方法2.Integer i = new Integer("100");int num = i.intValue(); //调用对象的方法方法3.int num = Integer.parseInt("1000"); //这是Integer的静态方法。
推荐:
int -> String : num + ""String -> int: Integer.parseInt(s)
自动装箱与自动拆箱:
装箱:基本数据类型变成包装类对象。拆箱:相反
自动装箱应用场景:
Integer i = 10; //将10这个基本数据类型转化成对象ArrayList list = new ArrayList(); list.add(1) ; //集合只能装对象,这里的1被自动装成对象
自动拆箱应用场景:
Integer i = 10; int num = i; //这里i被自动拆成基本数据类型,然后由基本数据类型接收
18-11-4:注释、变量、命名、转化.txt****
Java基础
·java跨平台:因为在不同的操作系统上有不同的jvm
jre:运行环境(包括jvm和核心类库)jdk:开发工具(包括了jre)
·注释:
// 单行注释/* */ 多行注释/** **/文档注释
·定义数据类型时的注意:
整形默认是int 浮点默认是double定义long时数字后加L定义float时数字后加F
·命名规则:
包:一定要小写,多级包用.分隔类:首字母大写方法和变量:首字母小写,后面每个单词首字母大写
·变量的域:
变量的使用,只能在其域中(此变量所在的大括号范围中)例如public class Main{public static void main(String args[]){{ /*代码块*/int c = 30;}System.out.print(c); //无法正常输出}}
·类型转换:
一般而言我们要求运算的类型一致如果不一致就会发生转换:隐式转换:byte、short、char -- int -- long -- float -- double (由低向高的转换顺序)参与运算的数据将自动转换成精度较高的数据,但高精度不可转化为低精度,避免造成缺失数据例如:byte a = 10;int b = 20;byte x = a + b; //b是int,a将转化成int,最终结果也为int,不可用低精度的变量接收int y = a + b;System.out.println(x);System.out.println(y);强制转换类型:强制将高精度转换成低精度,一般不这样做。例如: 如上byte x = (byte)(a + b); //这个时候就可以通过编译
18-11-5:字符串加法、双&、随机数、数组.txt****
·字符串参与加法运算
任何类型变量与字符串参与加法运算都是字符串的拼接System.out.println("a"+100); //a100System.out.println("a"+'e'); //ae
·&& 与 & 以及 || 与 | 在java中区别不大
但是&&在条件判断中如果前者为false后者不进行判断,而&无论如何两边都会去进行判断
·随机数
用 ctrl + shift + o 快捷键导包import java.util.Random; Random r = new Random();r.nextInt(100); //[0,100) 的随机数
·数组
基本使用int arr[] = new int[10]; //数组的初始化System.out.println(arr); //打印的是地址值 for(int i = 0; i < arr.length; i++){System.out.println(arr[i]); //每一个对象进行初始化时都有一个默认值,int的默认值是0}静态初始化:int[] a = {1,2,3};for(int e: a){ //类似于python的遍历System.out.println(e);}将数组赋值给数组int[] a1 = new int[3];int[] a2 = new int[10];for(int i = 0; i < a1.length; i++){ //对a1数组赋值a1[i] = i;}a2 = a1;System.out.println(a2.length); //尽管a2分配了10个空间,但a2这个变量指向了a1这个变量的地址,故a2的长度也变成了3for(int i = 0; i < a2.length; i++){a2[i] = 100 + i; //对a2进行赋值}for(int i = 0; i < a2.length; i++){System.out.println(a1[i]); //发现对a2的赋值影响到了a1}数组内存分配变量名放于栈中:int[] arr 对象放于堆中,每个对象都有默认值:new int[100] 遍历二维数组:int[][] a = {{1,2,3},{4,5,6},{7,8,9}};for(int i = 0; i < a.length; i++){for(int j = 0; j < a[i].length; j++){ //a[i]也是个数组System.out.print(a[i][j] + " ");}System.out.println();}
18-11-6:方法定义格式、方法重载、以及注意事项、方法参数是基本类型.txt****
·方法:
定义在主类当中格式:记住格式!public static int fun(int a, int b){}方法重载:定义:同一个类中出现了名字相同的方法参数特点:同名方法参数个数不一样同名方法参数类型不一样如果不满足以上两点:则报错注意:方法重载只比较参数,即只比较参数的个数和类型。对于参数的名字和方法返回类型不予考虑。整数默认是int,小数默认是double:例如:public static void main(String[] args) {System.out.println(fun(12.0,13.0)); //由于默认小数是double,所以调用double方法}public static boolean fun(double a, double b){System.out.println("double");return a == b;}public static boolean fun(float a, float b){System.out.println("float");return a == b;}如果想要调用float方法,要么在小数前加转化类型,要么在小数后加f如果方法的参数是基本数据类型:则方法对变量的操作不影响实参例如: change(a,b) //a还是a,b还是b,不会交换
18-11-8:方法参数是引用类型、断点调试、面向对象格式、初始化值问题、内存分配(重点).txt****
·如果方法的参数的类型引用型参数,方法会影响该引用型变量
public static void main(String[] args) {int[] arr = {1,2,3,4,5};change(arr); //将arr作为参数传进去for(int i = 0; i < arr.length; i++){System.out.println(arr[i]); //此时数组的元素全部乘了2}}public static void change(int[] a){for(int i = 0; i < a.length; i++){a[i] *= 2;}}
·断点
基本操作和Dev C++ 一样
·面向对象:
类中的方法定义:public int fun(..) // 去掉主类中的static类中的属性可以不用设值,原因请参考"初始化值的问题"
.初始化值的问题:
在java中数组在定义时每个元素有初始化值;构建类时,每个属性也有初始化值;除了数组和类以外,其他所定义的任何变量都没有初始化值。例如:int i;String s;syso(i);syso(s); //都是The local variable 变量名 may not have been initialized原因分析:如果定义一个基本数据类型,它们是放在栈中,值也保存在栈中,没有赋予初始值,要使用前必须赋值。而数组和对象是new出来的,它们保存在堆中,堆内存一开始就为它们赋予了初始值
JAVA变量内存分配:
方法区:javac编译后的 字节码文件 都放在 方法区 中,每个字节码文件就是一个类(这也是为什么类名要和文件名一致)。方法 和 属性 也在方法区中的 字节码文件 。栈:当 调用某方法 时就会将方法 加载到栈 中,方法中的变量也会加载到栈中。如果这些变量是 基本数据类型,其值和变量一起放在栈中。而且变量 没有初始值 。如果是 引用类型,其引用变量和其对象的 地址 也一起放在栈中, 指向堆 中的具体对象。如果栈中的方法执行完,其分配的内存就自动被垃圾回收机制回收。堆:如果是new出来的引用数据,就放在堆中。堆中对象的属性一般是基本数据类型,且都有初值。堆中存储对象的方法只是 存储其在方法区的地址 。
18-12-10:多异常处理顺序、finally、IO流标准处理异常格式、异常分类、自定义异常(代码)、异常总结.txt****
多个异常的处理:
允许处理多个异常,平级异常次序不重要。有子父级关系的话:子异常一定放在父异常前面。(如果父异常在前,那么就轮不到子异常处理,编译都通过不了)。
finally–不管try…catch处理异常是否成功,finally中一定执行。
例如:try {System.out.println(5 / 0);} catch(NullPointerException e) { //上面的异常无法捕获到。System.out.println("空指针"); } finally {System.out.println("释放资源");}结果:释放资源 //即使atch没有处理成功,但finally一定执行。Exception in thread "main" java.lang.ArithmeticException: / by zeroat com.异常处理.TryCatchDemo.main(TryCatchDemo.java:11)
IO流的异常处理格式(标准格式):
FileWriter fw = null; //将fw对象初始化,防止空指针异常,以后也一定写成这种样子。try {fw = new FileWriter(");fw.write("aaaaa");} catch (IOException e) {System.out.println("出现IO流异常");} catch (Exception e) {System.out.println("出现其他异常");} finally { try {if(fw != null) { //fw非空才将其关闭。fw.close();} } catch (Exception e) {System.out.println("关闭时发生异常");}}
异常的分类:
运行时期异常:可以不处理,且一定是java.lang.RuntimeException的子类。编译时期异常:写完必须处理,否则系统不准运行。非java.lang.RuntimeException的子类。
throw 与 throws:
throw是一种制造异常的方式。throws是一种处理异常的方式,是无法处理异常然后抛出去给调用者处理的方式。
自定义异常:
定义编译异常:只要继承Exception,然后写好构造方法就可以了。定义运行异常:只要继承RunTimeException然后写好构造方法就可以了。
自定义异常的例子(定义一个编译时期异常):
MyException.java
能够产生异常对象的类
public class MyException extends Exception {
各种构造方法...
}
Demo.java
public class Demo {
public static void main(String[] args) {try {checkScore(111); //由于定义的是编译时期异常,要么处理,要么抛给虚拟机,总之一定要处理} catch (Exception e) {System.out.Message());}}//此方法用于决定是否生成异常对象。如果满足条件则抛出异常。public static void checkScore(int score) throws MyException { //由于可能会产生异常,所以一定要在方法后面加上抛出哪种异常的可能。if(score > 100 || score < 0) {throw new MyException("成绩异常"); //如果抛出异常代表着方法的结束}System.out.println("成绩正常"); //如果没有抛出,则方法会一直执行到这。}
}
结果: 成绩异常
总结:
1.不管atch处理异常是否成功,finally中一定执行。2.FileWriter fw = null; 以后声明对象时一定设置为null。3.如果抛出异常,其所在的方法名后一定要加上"throws 异常类型"!!这是为了告诉虚拟机此方法可能会抛出xx异常。4.如果抛出运行异常,可以不用在方法后面throws,但是最好加上!!5.如果一个方法throws 编译异常,不管该方法是否有无throw异常,调用此方法时一定要进行处理!一定要处理!6.方法中如果抛出了异常(throw),则该方法就结束了。7.父异常要后catch
18-12-12:File类的概述、构造方法、创建、删除、获取、修改、判断功能.txt****
File类的使用:
概述:File可创建一个指向文件或者文件夹路径的对象,并可以进行一系列操作。构造方法:(注意:该文件或者文件夹不一定存在)File(File parent, String child) parent是一个文件夹的file对象,child是文件名称 File(String pathname) 一个文件或者文件夹的绝对路径 File(String parent, String child) parent是文件夹路径,child是文件的名称 创建功能:boolean createNewFile()创建文件 boolean mkdir() 只能在已经存在的目录中创建创建文件夹。boolean mkdirs() 可以在不存在的目录中创建文件夹。删除功能:boolean delete()可以删除文件或者文件夹,但如果文件夹下有子文件或子文件夹,则无法删除。(安全起见)判断功能:boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。 boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。 boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。 boolean exists() 测试此抽象路径名表示的文件或目录是否存在。 boolean isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件。 获取和修改功能:File getAbsoluteFile() 返回此抽象路径名的绝对路径名形式。 String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。 String getName() 返回由此抽象路径名表示的文件或目录的名称。 String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。 File getParentFile() 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。 String getPath() 将此抽象路径名转换为一个路径名字符串。 boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。 String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。 File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
18-12-13:IO流分类、用字节流进行图片复制、提一下标准输入出流、以后采用数组复制方式.txt****
IO流高级:
IO流分类(按数据类型):字节流:字节输入流: InputStream字节输出流: OutputStream字符流:字符输入流: Reader字符输出流: Writer
用字节流复制图片:
public static void Chars() throws FileNotFoundException, IOException {//创建对象FileInputStream fis = new FileInputStream("C:\Users\熊汝成\Pictures\Saved Pictures\timg .jpg");FileOutputStream fos = new FileOutputStream("裴秀智.jpg");byte[] bs = new byte[1024];int len;while ((len = ad(bs)) != -1) {fos.write(bs, 0, len); }fis.close();fos.close();System.out.println("成功");}注意点:1.字节流不需要flush,字符流才需要flush。2.以后用数组方式进行复制,高效。
标准输入输出流:
System.in 标准输入流:用于录下键盘中输入的数据System.out 标准输出流:用在在终端中输出数据
18-12-16:isr与osw的介绍、字符流的操作,字节流的功能.txt****
1.OutputStreamWriter的引用–问题:将数据输出到终端
//输入流对象建立BufferedReader br = new BufferedReader(new FileReader("));//标准输出流对象的建立OutputStream os = System.out; //多态String line;while ((line = br.readLine()) != null) {os.Bytes()); //必须将字符串转化成字节流数组才可以os.write("n".getBytes());}br.close();os.close();从上可以看出,当使用OutputStream写入必须是字节或字节数组,现在不想将字符串传换成字节数组。引入OSW------------------------------------------------------------------------------------改进源码//输入流对象建立BufferedReader br = new BufferedReader(new FileReader("));//标准输出流对象的建立OutputStreamWriter osw = new OutputStreamWriter(System.out); String line;while ((line = br.readLine()) != null) {osw.write(line); //像字符流一样的操作了osw.write("n");}br.close();osw.close();
2.终端写入数据:
InputStream is = System.in;FileWriter fw = new FileWriter(");byte[] bs = new byte[1024];int len;while ((len = is.read(bs)) != -1) { //is只能读字节数组fw.write(new String(bs,0,len)); //把字节数组转化成字符串fw.flush();}is.close();fw.close();-----------------------------------------改进:InputStream is = System.in;InputStreamReader isr = new InputStreamReader(is);FileWriter fw = new FileWriter(");char[] chs = new char[1024];int len;while ((len = ad(chs)) != -1) {fw.write(chs,0,len);fw.flush();}is.close();fw.close();
总结:
InputStreamReader和OutputStreamWriter还是字符流,是包装了字节流的字符流!他们构造方法中传入字节流对象,然后操作上就是字符流的操作。这样做到了"字节流的功能,字符流的操作"
18-12-18:字符打印流的概述.txt****
打印流PrintWriter:
概述:同FileWriter一样,也可以对文件进行写入字符流数据。复制文本:BufferedReader br = new BufferedReader(new FileReader("));//pw的构造方法很多,此构造方法是为了打开自动刷新的功能PrintWriter pw = new PrintWriter(new FileWriter("D:\"), true); String line; while ((line = br.readLine()) != null) {pw.println(line);}/** 即使没有刷新,没有关闭文件,同样也能进行自动刷新和换行。*/
18-12-18:对象操作流的使用.txt****
对象操作流:
概述:可以将对象输入到文件当中。ObjectInputStream:构造方法:传入一个InputSteam及其子类的对象。读取对象的方法adObject() 抛出编译异常ClassNotFoundException(如果这个对象的类找不到了)读取文本对象的方法:方法一:如果文件中全是对象try {while (true) {Object o = adObject();System.out.println(o);}} catch (EOFException e) {System.out.println("文件读完");}方法二:如果文件中是一个集合ArrayList<Student> list = (ArrayList<Student>) adObject();for (Student student : list) {System.out.println(student);}ObjectOutputStream:构造方法:传入一个OutputSteam及其子类的对象。写入对象的方法:oos.wirte()注意:1.构造方法一定是传入一个字节输入流或者字节输出流。2.写入的对象一定要实现Serializable这个接口。
18-12-19:IO流的大总结.txt****
IO流的总结:
File:是指向文件或者文件夹路径的一个对象。知识点:构造方法、创建、删除、获取、判断、修改等功能。
FileInputStream、FileOutputStream:对文件的读写(以字节为单位)知识点:构造方法:传入File对象或者String(传入String其实是自动创建File对象) 主要方法:int read()---返回数字。int read(byte[] b)---将字节流存到byte数组中。void write(byte[] b, int off, int len) ---将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 void write(int b)--- 将指定字节写入此文件输出流。 注意要点:不管是读还是写,都是以字节byte为单位。写入数据不需要flush刷新。
FileReader、FileWriter:对文件的读写(以字符为单位)注意要点: 大部分知识点和fis、fos一样。写可以写入各种数据类型(String、int、),但读写都是以char为基本单位。写入数据需要flush刷新。
InputStreamReader、OutputStreamWriter:字节流的功能字符流的操作知识点: 构造方法:传入InputStream、OutputStream子类的对象。注意要点: 该类的方法同Reader、Writer的操作是一样的。它是将字节流的能力包装成字符流的操作。
PrintWriter:打印流知识点: 构造方法: 传入File、Writer、OutputStream都可以注意要点: 其实同FileWriter类似,不过他有自动刷新和自动换行的功能。
BufferedWriter、BufferedReader:缓冲流 知识点: 构造方法:传入Reader、Writer对象。注意要点: 能够更加高效的处理字符流。可以读取一行和独特的换行功能。
ObjectInputStream、ObjectOutputStream:对象操作流 知识点: 构造方法: 传入InputStream、OutputStream对象 主要方法: readObject() 抛出编译异常ClassNotFoundException ,读完所有对象会抛出EOFExceptionwriteObject() 写入对象注意要点: 加入的对象的类必须实现接口Serializable
总而言之:
1.fis,fos,fw,fr的构造方法都是传入File对象。主要方法是read和write,写的单位是byte和char。字节不刷新字符要刷新。2.br和bw把fr与fw包装进去,能够提供高效。newLine和readLine是独特方法。3.对象操作流的构造方法是传入字节流(一般是FileInputStream和FileOutputStream),加入的对象一定要实现接口。读对象可能
找不到类所以抛出一个编译异常,读完文件会抛出一个运行异常。
18-12-20:Properties与IO流的结合.txt****
Properties与IO流的结合: 有种专门的文件是 xxx.properties
Properties的概述:类似于Map,但键值对只能是String。被称为属性列表。基本功能:存数据:setProperty(String key, String value) 拿数据:getProperty(String key) 遍历数据:Set<String> stringPropertyNames() 可以获取所有的键集源码演示://创建Properties对象Properties pro = new Properties();//存入数据pro.setProperty("001", "xrc");pro.setProperty("002", "lw");//遍历Set<String> keys = pro.stringPropertyNames(); //获取到了所有的键。for (String key : keys) {String value = Property(key);System.out.println(key + "=" + value);}-------------------------------------------------------------------------------------------------与IO流的结合:具体方法:写出数据:void store(OutputStream out, String comments) void store(Writer writer, String comments) 读入数据:void load(InputStream inStream) void load(Reader reader) 源码演示: /** 将属性列表放入到文件当中**///创建属性列表对象 Properties prop = new Properties();//创建输出流对象FileWriter fw = new FileWriter(new File("学生"));//添加键值对关系prop.setProperty("001", "熊汝成");prop.setProperty("002", "刘威");prop.setProperty("003", "周玄");//将关系存放到文件当中prop.store(fw, "存放学生对象");//释放资源fw.close();===========================================/** 将文件中的关系读入到属性列表中*///创建一个空的属性列表Properties prop = new Properties();//创建输入流对象FileReader fr = new FileReader(new File("学生"));//从文件中读取数据prop.load(fr);//释放资源fr.close();//遍历属性列表,看是否加载成功Set<String> keys = prop.stringPropertyNames();for (String key : keys) {String value = Property(key);System.out.println(key+"="+value);}
18-12-20:关于固定序列化ID的必要性.txt****
关于序列化接口ID的问题:
存入一个学生对象后,对学生类进行了修改。在进行读入的时候,就会抛出java.io.InvalidClassException异常。原因:将学生类写好并实现序列化接口后则系统会分配一个默认的序列化ID,且每次对学生类进行修改后则序列化ID会改变。当进行读学生操作的时候,发现读的学生类型的序列化ID和现有学生类型的序列化ID不同时,则抛出异常。措施:在学生类写好并实现了序列化接口以后,则立马固定住序列化ID,这样无论怎么修改,ID不变。就不会抛出错误。直接在Student类中写一个成员变量 private static final long serialVersionUID = 8846915965544563304L;
18-12-22:Map和List都实现了序列化接口、关闭最外层stream或er便可。.txt****
1.JAVA中的Map、List都是实现了序列化接口,都可以将其存到文件当中。
2.JAVA的IO包下的stream和er都是装饰者模式,只需要调用最外层的close方法就能将内部的stream或er一并关闭。
18-12-26:多线程的概述、多线程的第一种实现方式.txt****
多线程的概述:
进程:可以理解为一个程序。单线程:一个进程中只做一件事情。安全,效率低。多线程:一个进程中做多个事情。不安全,效率高。
执行多线程的步骤:
1.创建类并继承Thread 2.将要执行的代码放在void run()中。3.在主方法中创建对象。4.调用对象的start方法,该方法会自动执行run中的代码。代码如下:主类:public class ThreadDemo {public static void main(String[] args) {MyThread mt = new MyThread();HerThread ht = new HerThread();mt.start();ht.start();}}---------------------------------------------------线程类:public class MyThread extends Thread {public MyThread(){setName("熊汝成");}@Overridepublic void run() {for (int i = 1; i < 3 ; i++) {System.out.println("这是"+getName()+"的第"+i+"个线程!");}}}class HerThread extends Thread {public HerThread() {setName("李育霖");}@Overridepublic void run() {for (int i = 1; i < 3; i++) {System.out.println("这是"+getName()+"的第"+i+"个线程!");}}}结果:不唯一。这是李育霖的第1个线程!这是熊汝成的第1个线程!这是熊汝成的第2个线程!这是李育霖的第2个线程!
18-12-26:有关异常中空指针问题、学生管理系统中常出现EOF解决.txt****
关于JAVA的try中的问题:
try {FileReader fr = new FileReader(");} catch (FileNotFoundException e) {System.out.println("没有此文件");}fr.close(); //此时fr会亮红线
Java严格讲究代码块的域,出了域绝对找不到变量。fr是一个放在try的代码块中,fr.close()自然
找不到fr变量。修改方式:
FileReader fr = null;try {fr = new FileReader(");} catch (FileNotFoundException e) {System.out.println("没有此文件");}fr.close(); //但会抛出运行异常java.lang.NullPointerException
fr首先是个null,try中的赋值语句没有成功,所以fr一直是null,修改:
FileReader fr = null;try {fr = new FileReader(");} catch (FileNotFoundException e) {System.out.println("没有此文件");}if (fr != null){fr.close();} //这样才是正确的方式。
在写学生管理系统的时候,如果"学生.txt"是一个空文件,在构造ObjectInputStream对象时就会报EOF异常。
看看我是如何排错的:
ObjectInputStream ois = null; //先设立为nulltry {ois = new ObjectInputStream(new FileInputStream("学生")); //尝试下创立ois对象} catch (EOFException e) {HashMap<String, Student> map = new HashMap<String, Student>(); //如果报错就添加一个空map进去ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("学生"));oos.writeObject(map);oos.close(); ois = new ObjectInputStream(new FileInputStream("学生")); //再创立一次ois对象}
18-12-2:容器中元素的遍历(转化数组、迭代器)、迭代器中的并发异常、修改迭代器中的元素也会修改原容器中的元素.txt****
元素的遍历:
方法一:转化成object数组,再进行遍历。//方法一,转化成数组进行遍历Collection c = new ArrayList();c.add("hello");c.add("java");c.add("xiongrucheng");Object[] os = c.toArray();for(int i = 0; i < os.length; i++){System.out.println(os[i]);}方法二:转化成迭代器对象,进行遍历:Collection c = new ArrayList();c.add("hello");c.add("java");c.add("xiongrucheng");Iterator it = c.iterator();while(it.hasNext()){System.out.());}
解决迭代器中的并发异常:
由于迭代器是集合的副本,必须与集合相一致。如果迭代器中的元素没有变,但集合中的元素发生改变就会造成:Exception in thread "main" java.util.ConcurrentModificationException(并发修改异常)如果集合中的元素没有变,修改迭代器,迭代器会影响集合的变化。//声明一个List对象List list = new ArrayList();//添加三个元素list.add("hello");list.add("java");list.add("xiongrucheng");//调用list.listIterator() 制造一个列表迭代器,因为列表迭代器拥有add方法ListIterator itor = list.listIterator();System.out.println(list); //结果:[hello, java, xiongrucheng]while(itor.hasNext()){String s = ((); //()转化一个String对象,向下转型if(s.equals("java")){itor.add("python"); //注意,如果是list.add("python")会引发异常,所以是迭代器中添加元素}}System.out.println(list); //[hello, java, python, xiongrucheng] //迭代器的变化造成了原集合的变化
迭代器可以对原集合进行永久改变:
LinkedList<Student> list = new LinkedList<Student>();//添加元素list.add(new Student("熊汝成", 19));list.add(new Student("刘威", 18));list.add(new Student("李凯文", 20));//通过迭代器进行修改,通过迭代器,将每一个元素的名字和年龄修改Iterator<Student> itor = list.iterator();while(itor.hasNext()){Student s = ();s.setAge(0);s.setName("无名氏");}//在进行遍历原列表for (Student student : list) {System.out.println(student);}结果:Student [name=无名氏, age=0]Student [name=无名氏, age=0]Student [name=无名氏, age=0] //发现利用迭代器进行操作了以后,原集合也都改变了。
18-12-2:泛型和增强for循环.txt****
泛型:
在java的集合类中,有许许多多的泛型。因为集合可以添加任何类型元素,泛型可以将集合像数组一样,规定添加元素的类型。
增强for循环:
for(ElemType e : 集合对象){}
18-12-3:List中的增删查改、元素是对象时的排序(附加源码)、foreach的修改元素.txt****
List对象中的操作:
初始化: List<Student> mylist = new LinkedList<Student>();//其实增删查改同ArrayList一样。添加:mylist.add();删除ve();查找()修改:mylist.set()排序:Collections.sort(列表)注意:1.列表中的元素的类型(比如Student),一定要实现Compareble,且重写 int compareTo(E o)方法。2.返回值是一个整形,是自己的属性与对方的属性的差值。
对于ArrayList,上述也是如此。
具体用ArrayList还是LinkedList,取决于你是增删多,还是查改多。
foreach对于元素是基本数据类型的数组修改无效,对于元素是引用类型的数组修改有效.
例如:for (Student student : list) {student.name = "hhh"; //list中的元素是引用数据类型,foreach修改成功}for(int i : intArray){i = 20; //intArray中的元素是int,foreach不可修改}
源码:
Demo.java
package com.sort_and_find;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Demo {
public static void main(String[] args) {List<Student> list = new LinkedList<Student>();//添加学生list.add(new Student(1709301, "zw", 108));list.add(new Student(1709305, "xrc", 19));list.add(new Student(1709302, "laowang", 50));//先输出学生for (Student student : list) {System.out.println(student.schoolnumber+"-"+student.name+"-"+student.age);}System.out.println("------------");//排序Collections.sort(list);//再输出,利用迭代器Iterator<Student> itor = list.iterator(); //注意,迭代器也要指定泛型while(itor.hasNext()){Student student = ();System.out.println(student.schoolnumber+"-"+student.name+"-"+student.age);}//利用二分法来查找/** 利用二分法,首先要排好序* 其次,查找是根据Student中compareTo方法比较的何种属性进行查找的*/int index = Collections.binarySearch(list, new Student(1709302,"laowang",108));System.out.println(index);}
}
Student.java
package com.sort_and_find;
public class Student implements Comparable{
int schoolnumber;String name;int age;public Student() {super();// TODO Auto-generated constructor stub}public Student(int schoolnumber, String name, int age) {super();this.schoolnumber = schoolnumber;this.name = name;this.age = age;}@Overridepublic int compareTo(Student o) {// TODO Auto-generated method stubreturn this.age - o.age; //根据年龄比较}
}
结果:
1709301-zw-108
1709305-xrc-19
1709302-laowang-50
1709305-xrc-19
1709302-laowang-50
1709301-zw-108 //根据年龄排序
2 //只能根据年龄进行查找
18-12-4:collections工具类中对容器的洗牌与旋转.txt****
洗牌与旋转:
Collections提供了以下方法:洗牌:public static void shuffle(List<E>list) 可以将数据重新排列。旋转:public static void rotate(List<E>list, int distance)逆转:public static void reverse(List<E> list)
18-12-4:有关HashMap的相关操作,特别是遍历.txt****
散列映射(字典)的基本操作:
1.初始化:HashMap<String, Student> map = new HashMap<String, Student>();2.添加元素:map.put("xiongrucheng", new Student("熊汝成", 19));3.输出map中的元素个数syso(map.size())4.根据键来查询元素Student s = ("xiongrucheng");System.out.println(s); //结果:Student [name=熊汝成, age=19]5.查询是否包含该键:System.out.ainsKey("xiongrucheng")); //结果:true6查询是否包含该值:System.out.ainsValue(new Student("威威", 50))); //结果,false,因为两对象地址不同7.移除ve("likaiwen");8.遍历://map.values()将返回一个实现了Collection<Student>接口类创建的对象。个人理解应该是返回了一个实现了Collection的//匿名内部类的对象。并将该对象赋值给接口变量。Collection<Student> c = map.values();//c因为实现了接口的方法,所以可以返回一个确确实实的迭代器。Iterator<Student> itor = c.iterator();//遍历迭代器while(itor.hasNext()){System.out.());}//当然,也可以用foreach来遍历这个对象Collection<Student> values = map.values();for (Student student : values) {System.out.println(student);}9.清空:map.clear(); 10.键值对的遍历:上面的8是对键或者对值的单独遍历,现在讨论键值对的遍历方法一:public static void Method1(Map<String, String> map) {//通过对键的遍历,一个个的遍历MapSet<String> keys = map.keySet();for (String key : keys) {String value = (key);System.out.println(key + "--" + value);}}方法二://利用Map中的内部类进行遍历public static void Method2(Map<String, String> map) {Set<Map.Entry<String,String>> entrys = Set(); //Map.Entry是Map中的内部类for (Map.Entry<String, String> entry : entrys) { System.out.Key()+"--"Value());}}注意点:如何通过键进行对值的修改?只需要重新put()就可以进行覆盖修改了
18-12-4:栈的基本操作.txt****
栈堆:
boolean empty() 测试堆栈是否为空。 E peek() 查看堆栈顶部的对象,但不从堆栈中移除它。 E pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。 E push(E item) 把项压入堆栈顶部。 int search(Object o) 返回对象在堆栈中的位置,以 1 为基数。
18-12-5:List中的排序(详解),Comparable与Comparator的区别(内外比较器的比较)、学生集合各个属性排序(完整代码).txt****
List中的排序问题:
1.对于基本数据类型:正序Collections.sort(list);逆序Collections.sort(list,new Comparator<Integer>(){ //实现一个Comparator的内部类对象public int compare(Integer o1, Integer o2) {return o2 - o1;}});2.对于引用数据类型的排序:方法一:利用匿名类实现Comparator<Student>接口Collections.sort(list,new Comparator<Student>(){@Overridepublic int compare(Student o1, Student o2) {Rank() - o2.getRank(); //根据名字排序:Name()Name());} });方法二:Student类中实现Comparable<Student>接口类:public class Student implements Comparable<Student>{...}重写方法:@Overridepublic int compareTo(Student o) {return o.rank - this.rank;}
Comparable 与 Comparator的区别:
内比较器:Comparable形容词,表示可比较的。这种接口往往是需要类去实现的,从而增加类的一个“可比较”功能。外比较器:Comparator表示比较器,一般是通过内部类实现该接口的功能,用于给Collections.sort()传递参数。一般推荐这种方式。
对学生的各个属性排序的完整代码:
package com.sort_and_find;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SuperDataDemo{
/**静态的成员内部类*/static class sortByName implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {Name()Name());}}static class sortByAge implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {Age() - o2.getAge();}}static class sortByRank implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {Rank() - o2.getRank();}}public static void main(String[] args) {List<Student> list = new ArrayList<Student>();//添加学生list.add(new Student("jack", 45, 'a'));list.add(new Student("beak", 20, 'c'));list.add(new Student("tom", 90, 'f'));list.add(new Student("keven", 31, 't'));list.add(new Student("anny", 8, 'e'));//遍历for (Student student : list) {System.out.print(student);}System.out.println();//排序,根据xx来排序Collections.sort(list, new sortByRank());//遍历for (Student student : list) {System.out.print(student);}System.out.println();}
}
18-12-9:异常的处理、抛出(初步,后续还有补充).txt****
异常处理:
1.异常体系:超类:java.lang.Throwable--->java.lang.Error(不可扭转的的错误), java.lang.Exception(可处理的异常)2.异常处理的方式:捕获并处理异常抛出异常3.捕获并处理异常atch语句:格式:try{可能发生异常的语句} catch(异常类型 e){处理语句}注意点:1.发生异常后,如果没有atch语句,则jvm会自动关闭程序。2.如果写了语句,发生异常后自动跳转到catch中,不会再跳回try语句中。例如:代码:try{System.out.println("try的第一条");System.out.println(4/ 0);System.out.println("try的第二条"); //跳转到catch中,不会再回来} catch(Exception e){System.out.println("发生异常");}结果:try的第一条发生异常4.抛出异常:异常都是发生在某个方法当中,如果没能力处理或者不想处理该异常,就可以将异常抛出去,交给调用方法的人去处理。格式:方法名() throws 异常类型{} //注意,异常类型可以写此异常类型的父类型。
抛出异常还遗留许多问题,见后续补充
19-1-10:TCP通信的补充点.txt****
TCP协议进行数据通信的注意点:
1.输入流--------------相互连接--------------输出流| | | || |客户端Socket 服务端Socket | || || | 输出流--------------相互连接---------------输入流如图所示,客户端的Socket与服务端accept后的Socket的交错连接。调用getInetAddress()方法获取的是对方的IP对象。2.Java的socket是一个全双工套接字,任何的输入流或输出流的close()都会造成Socket关闭。所以,不要用close方法关闭socket的IO流,可以用shutdown方法。
19-1-13:单元测试****
Junit单元测试:
在主类中的方法中添加注解@Test、@After、@Before便可进行单元测试,且方法不可是静态方法。
19-1-5:InetAddress类的简要了解.txt****
InetAddress类的介绍:
概述:此类表示互联网协议 (IP) 地址。初始化方法:static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。 host可以是主机名,也可以是ip地址。获取方法:String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。 String getHostName() 获取此 IP 地址的主机名。 static InetAddress getLocalHost() 返回本地主机。
19-1-5:主方法的运行是单线程的、多线程的第二种实现方法.txt****
主方法是单线程的,在主方法中调用各种方法时,程序是从上往下,从左往右运行。
实现多线程的第二种方式:
1.创建一个类实现接口Runnable,并重写run方法。2.在主方法创建类实例mt。3.在主方法中创建Thread实例t,并将mt对象传递进去。4.调用start方法,开启线程.代码如下:主类:public class ThreadDemo {public static void main(String[] args) {//创建MyThread对象MyThread mt = new MyThread();//创建第一个Thread对象,将mt传进去。Thread t = new Thread(mt);t.setName("老王");//创建第二个Thread对象,将mt传进去Thread t2 = new Thread(mt);t2.setName("老张");t.start();t2.start();}}自定义类:public class MyThread implements Runnable {@Overridepublic void run() {for (int i = 1; i < 4; i++) {System.out.println(Thread.currentThread().getName() + //静态的获取当前线程的方法"的" + i + "个线程");}}运行结果:老张的1个线程老王的1个线程老王的2个线程老王的3个线程老张的2个线程老张的3个线程第二种方法的意义:第一种方法是继承,第二种方法是实现,二解决了一的多继承问题。
19-1-5:利用同步代码块或同步方法解决多线程中的并发问题.txt****
多线程可能遇到的问题:
当有多个线程。多个线程共享一个数据源。就有可能会造成数据重复执行等问题。为了解决这个问题,引进同步代码块的概念。
同步代码块:
格式:synchronized (this) {每一个线程的运行代码。}作用:当线程的运行代码被synchronized(this){}包住以后,当运行这个线程时,将会开启一个锁,其他线程暂时无法运行。
源码:
public class MyThread implements Runnable {
int count = 100; //票的总数@Overridepublic void run() {while (true) {try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (this) { //需要进行封锁的地方,加上同步代码块if (unt > 0) {System.out.println(Thread.currentThread().getName() + "第" + unt + "张票正在出售");unt --;}}}}
}
public class ThreadDemo {
public static void main(String[] args) {//实例化mt对象.MyThread mt = new MyThread();//实例化多线程窗口一Thread t1 = new Thread(mt);t1.setName("窗口一");//实例化多线程窗口二Thread t2 = new Thread(mt);t2.setName("窗口二");//实例化多线程窗口三Thread t3 = new Thread(mt);t3.setName("窗口三");//实例化多线程窗口四Thread t4 = new Thread(mt);t4.setName("窗口四");//启动线程t1.start();t2.start();t3.start();t4.start();}
}
同步方法:
将synchronized放在run方法前面作为修饰符修饰,就可以将整个方法锁住。@Overridepublic synchronized void run() { ... } //用synchronized修饰后也是重写方法。
19-1-6:利用UDP协议发送并接收数据.txt****
使用UDP协议发送数据:
步骤:1.创建发送端对象DatagramSocket类的对象。2.创建数据包对象DatagramPacket类的对象,包含了数据,ip地址,端口号。3.发送出去。4.释放资源创建发送端对象DatagramSocket类的对象:使用无参构造,因为发送端不关心端口号。DatagramSocket ds = new DatagramSocket();创建数据包对象DatagramPacket类的对象,包含了数据,ip地址,端口号。DatagramPacket dp = new DatagramPacket(bys, length, address, port); 发送数据:ds.send(dp);
发送端完整程序:
public class UDPSendDemo {
public static void main(String[] args) throws IOException {//1.创建发送端对象DatagramSocket类的对象。DatagramSocket ds = new DatagramSocket();//2.创建数据包对象DatagramPacket类的对象,包含了数据,ip地址,端口号。String content = "你好,我叫熊汝成";byte[] bys = Bytes(); //将字符串转化成字节数组int length = bys.length;InetAddress address = ByName("192.168.190.1"); //创建InetAddress对象。int port = 8888;DatagramPacket dp = new DatagramPacket(bys, length, address, port);//3.发送出去。ds.send(dp);//4.释放资源ds.close();}
}
UDP协议接收数据:
步骤: 1.创建DatagramSocket对象2.创建Datagrampacket对象,这是一个容器,接收数据要用到3.接收数据,将数据放在包中。4.解包,获取包中的各项数据5.释放资源创建DatagramSocket对象:注意,要与发送端的端口号一致。DatagramSocket ds = new DatagramSocket(8888);创建Datagrampacket:使用DatagramPacket(byte[] buf, int length)构造便可,因为只是为了接收数据,创建一个容器便可。接收数据,将数据放在包中ive(dp); //这样就将数据放在了容器dp中。解包,获取包中的各项数据:通过dp中的各种get方法得到数据。
完整程序:
public class UDPGetDemo {
public static void main(String[] args) throws IOException {//1.创建DatagramSocket对象DatagramSocket ds = new DatagramSocket(8888);//2.创建Datagrampacket对象,这是一个容器,接收数据要用到DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);//3.接收数据,将数据放在包中。System.out.println("准备接收数据");ds.receive(dp); System.out.println("接收到了数据");//4.解包,获取包中的各项数据byte[] bys = dp.getData();InetAddress address = dp.getAddress();int length = dp.getLength();String content = new String(bys, 0, length);System.out.println("sender -->" + HostName());System.out.println("content -->" + content);//5.释放资源ds.close();}
}
注意:在第75行会有发生堵塞,打开接收端后程序会一直运行,直到收到消息。
19-1-9:利用TCP协议进行数据的发送和接收.txt****
利用TCP协议进行发送数据:
步骤:1.创建Socket对象2.从Socket对象中获取输出流对象。3.利用输出流发送数据4.释放资源创建Socket对象:Socket(InetAddress address, int port) //对方的IP地址和端口号从Socket对象中获取输出流对象:OutputStream os = s.getOutputStream();利用输出流发送数据:os.write(byte[]);
利用TCP协议进行接收数据:
步骤: 1.创建ServerSocket对象。2.利用此对象返回一个Socket对象,用于监听(堵塞)3.获取输入流对象4.获取数据5.释放资源创建ServerSocket对象:ServerSocket ss = new ServerSocket(9999); //本机端口号利用此对象返回一个Socket对象,用于监听(堵塞):Socket s = ss.accept(); //在此处程序堵塞获取输入流对象:InputStream is = s.getInputStream();获取数据:String sender = s.getInetAddress().getHostAddress() + "--" InetAddress().getHostName();byte[] bys = new byte[1024];int len;len = is.read(bys);String content = new String(bys, 0, len);System.out.println("sender -->" + sender);System.out.println("content -->" + content);释放资源:s.close();
// ss.close(); //服务端不应该关掉。
2019-1-13:JAVA的类加载机制.txt****
JAVA的类加载机制:
1.加载class文件到内存2.将加载好的数据融合到jre这个大的环境中。3.进行一系列初始化的工作
本文发布于:2024-02-01 05:33:21,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170673679934256.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |