java基础 总结版

 

基础知识

对象和类:

Java中万物皆对象,而类是对一些具有相同属性或者行为的对象的抽象,是一个模板。

创建对象的5种方式

  1. 使用new关键字
  2. 使用Class类的newInstance方法
  3. 使用Constructor类的newInstance方法
  4. 使用clone方法
  5. 使用反序列化

类中含有

成员属性:在类内部,方法体外部,作用于整个类,

成员方法,和成员变量同级

局部变量,在方法体内部,作用于方法体。当成员变量和局部变量重名时,调用的时距离最近的变量。

局部变量就是在类中的方法中定义的变量,在方法中临时保存数据,局部变量存储在内存的栈中,生命周期是随方法的调用而存在,随方法的调用完毕而消失。

成员变量就是在类中定义,用来描述对象将要有什么,成员变量存储在内存的堆中,生命周期是对对象的存在而存在,随对象的消失而消失。

类变量,带有修饰符static的变量,随着属于类,随着类的创建而存在,其实例对象共享一个变量。

构造方法:一般用于初始化对象,当遇到继承的时候要注意关键字this和super,都只能存在于第一行,所以只能有一个!只能被new(实例化对象),不能被调用,

对象则是类的具体的实例,有具体的属性和行为。

基本数据类型:8

Byte(1字节)   short(2)   int(4)   long(8)   char(2)   boolean   float(4)   double(8)

类型转换:向上转型(小→大)       向下转型(大→小)

引用数据类型:数组,类,接口,

变量类型:成员变量,局部变量,类变量

访问权限:

Public:所有类可见

Private:同一类内部可见

Protented:对同以包内的类和不同包中的有继承关系的类可见

              实例化子类对象,子类不重写protected修饰的变量或方法,可在子类对象中调用父类属性或方法。(其实就是继承了父类,然后自身拥有了和父类相同的属性或方法,然后可以被调用,若此时把父类修饰符改为private,则子类对象中不能调用,就算实例化父类也不行!!!)

Friendly:同一个包内可见。

Synchronized:关于线程安全的时候的同步锁,当临界资源被争抢使用时需要添加,表示用以时间只能被一条线程使用。

Volatile:修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值,而且当成员变量发生变化时,强迫线程将变化值写回到共享内存。

Transient:临时变量

循环结构:do---while      while     for    foreach   iterator    listiterator

String:

       码点:unicode值               代码单元:对应的字符!!!

       String:长度不可变

StringBuffer:线程安全,速度慢,支持同步

StringBuilder:线程不安全,速度快,不可同步

关于String,StringBuffer,StringBuilder的区别,

String长度不可变,但是却可以让字符串被共享,只有字符串常量是被共享的,而+或substring等操作产生的结果并不是共享的,所以判断字符串是否相等的话不能用==,要用equals方法,==是判断是否放在了同一个地方。

数组:用来存放同一种类型的容器,由于是同一类型,所以操作时候不需要考虑类型转换问题,效率高!

类的加载:

类的加载指的是将类的.class文件中的二进制数据读入内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象放在堆区中,和方法区中的类就像镜面映射得到的一样。

类的加载是由类加载器完成的,类加载器通常是由JVM来提供的,类加载的过程是父亲委托机制,在这种机制中,先委托父加载器,直到根类加载器,然后再由最初的加载器加载,如果都无法加载则报错ClassNotFound的异常,

然后连接:负责把类的二进制数据合并到jre中,该过程又分为三个阶段:

       验证:确保被加载的类的正确性,包括四方面的检查:

  1. 类文件的检查:确保程序使用的是Java类文件的固定文件
  2. 语义检查:确保类符合Java语言的语法规定
  3. 字节码验证:确保字节码可以被jvm安全执行
  4. 二进制兼容验证:相互调用的类之间的协调一致

准备:jvm为类的静态变量分配内存,并设置默认的初始值,

解析:jvm会把类的二进制数据中的符号引用替换为直接引用

最后是类的初始化:为类的静态变量赋予正确的初始值

 

所有的jvm的实现,必须在每个类或接口在Java程序“首次主动使用“的才会初始化他们。

主动使用的六种情况

  1. 创建类的实例
  2. 访问某个类或者接口的静态变量,或者对该静态变量赋值
  3. 调用类的的静态方法
  4. 反射
  5. 初始化某个类的子类
  6. Jvm启动时被标明为启动类的类

自己的理解:当运行Java虚拟机的时候,第一件事就是寻找入口, main方法,test等等,于是加载器开始启动并找出xxx.class文件,,在对它进行加载的过程中,判断是否有基类(有的话继续向上加载...)然后基类中的static被初始化,→导出类的static初始化!然后就执行main方法中的代码!!!

第一部分:面向对象

抽象

对事物进行简化,只提取对问题的解决有帮助的部分。其余的部分全部舍弃。

封装

概念:属性私有化,对外提供公共的get(),set()方法。

举例:创建一个封装类,意思就是该类中是用来提供存放数据的,然后其数据对外是不可修改的(意思是不可以直接通过new对象,然后对象名.属性修改,只能通过提供的公共的set,get方法进行修改,这样的好处就是可以我们可以对类中的属性进行控制,不是任何数据都可以进行存储的。),

继承

子类拥有父类的所有属性和方法,并且还有自己特有的属性和方法。其实现的方式有extends和implements。

所有类的超类都是Object,其中有几个方法需要注意:

Equals():每个类都要有自己equals()方法,当对象内容需要进行比较的时候必须进行重写。

@Override

         public boolean equals(Object obj) {

                   if (this == obj)

                            return true;

                   if (obj == null)

                            return false;

                   if (getClass() != obj.getClass())

                            return false;

                   Equals other = (Equals) obj;

                   if (address == null) {

                            if (other.address != null)

                                     return false;

                   } else if (!address.equals(other.address))

                            return false;

                   if (age != other.age)

                            return false;

                   if (name == null) {

                            if (other.name != null)

                                     return false;

                   } else if (!name.equals(other.name))

                            return false;

                   return true;

hashCode():当重写equlas的时候必须重写hashCode(),因为equals是以hashCode为标准判断是否相等的。

@Override

         public int hashCode() {

                   final int prime = 31;

                   int result = 1;

                   result = prime * result + ((address == null) ? 0 : address.hashCode());

                   result = prime * result + age;

                   result = prime * result + ((name == null) ? 0 : name.hashCode());

                   return result;

         }

toString():重写其方法可以直接打印对象名,默认为对象名.toString()

clone():

关键字:extends   implements    instanceof

继承的设计技巧:

1.将公共操作和域放在超类中

2.不要使用受保护的域(原因1:任何一个人都可以由一个类派生出来一个子类,并编写代码直接访问protected的实例域,从而破坏了封装性!原因2:Java中在同一个包内的所有类都可以访问protected域,而不管它是否为这个类的子类)。

3.使用继承实现“is-a”关系

4.除非所有继承的方法都有意义,否则不要使用继承

5.在覆盖方法时,不要改变预期的行为。

6.使用多态,而非类型信息

7.不要过多的使用反射!反射适用于编写系统程序,通常不适用于编写应用程序。

三大修饰符:

Static:

       可修饰方法,变量,代码块,不可以修饰类!

       修饰方法时在调用该方法时不需要在实例化所在类,直接类名.方法名调用。随类的加载就被分配内存。可以被继承,没有多态。

       修饰变量时该变量代表类变量,该类的所有实例对象都公用一个。

修饰代码块,作用是给类进行初始化!优先于主函数的执行

       被static修饰过的就属于类,存在于对象之前!

Static:属于类修饰符,可以把相应的属性或方法变为类级别的,使之伴随类产生和销毁,局部变量不能被修饰为static,静态方法也不能使用非静态变量。

被static 修饰的变量称为静态成员变量或类成员变量。静态成员可以使用类名直接访问,也可以使用对象名访问,推荐直接使用类名访问。

静态成员还是属于成员变量,其生命周期还是随着类的调用而存在,随类的调用结束而消失。

 

被static修饰的方法成为静态方法,静态方法可以直接调用同类中的静态成员,但是不能直接调用非静态成员,(需要通过创建类的对象,然后通过对象来访问非静态成员),在普通成员方法中可以直接访问同类中的静态成员和非静态成员,静态方法不能直接调用非静态方法,需要通过对象来访问非静态方法。

 

总结:static 只能修饰变量和方法,不能修饰类!!!

修饰过的方法和变量可以在类中任何地方直接调用,没修饰的只能先实例化在调用。

 

代码块:静态代码块→初始化类

              动态代码块→初始化(所有)对象

              构造函数→初始化(特定)对象

Abstract:

       可修饰类,方法,修饰方法的时候不需要因为是抽象方法没有方法体,所以就不要写{},直接+;。

       修饰类的时候此类不可被实例化,只能被子类实现其抽象方法后通过实例化子类调用其属性方法,

       修饰的方法为抽象方法,只有声明没有实现,只能定义在抽象类中。

修饰类:抽象类,含有抽象方法的类一定是抽象类,抽象类中的抽象方法一定要被子类继承,若子类没有继承,则子类也一定为抽象类。可以由构造方法!!

方法:没有具体的方法体,只是一个抽象概念,需要被重写使用,只有声明没有实现。

 

Final:可修饰类,方法,变量。

       修饰类不能被继承,

       修饰方法可以被继承,不可以被重写!

修饰变量时表示该变量不可被修改,声明的同时进行初始化!局部变量可以先声明再初始化,但是在使用该变量之前一定要初始化!

抽象类:

如果一个类没有足够的信息来描述一个具体的对象,而需要其他具体的类来支撑它,我们称它为抽象类,如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的,如果从一个抽象类继承,并想创建它的对象,那么必须为基类的所有的抽象方法提供方法定义,否则子类也还是抽象类,还必须强制添加abstract。抽象类不能被实例化对象,就算类内部没有抽象方法,只要被定义为abstract,就不能被实例化!子类的抽象方法不能和父类抽象方法同名。

接口:

接口使得抽象类的概念更加上升了一步,更加纯粹,也不能被实例化,是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义,和类的定义基本相同,接口没有实例域,关键字改为interface,接口的方法自动为public abstract,实例变量也是static public,没有构造方法。在实现接口的时候,必须把方法声明为Public,

比如:要使用Arrays.sort()方法对一个类对象数组进行排序,则那个类一定要实现Comparable接口,接口中可以定义静态方法,一般是在实现自己定义的接口的时候可以定义静态方法,可以省略创建一个实现类的麻烦。还可以定义默认方法。

思考:你想使用我提供的方法,那么你就要按照我的标准去提供我所需要的资源,这样我才让你用我的东西!!!

接口的作用?(如何实现降低耦合)

降低耦合的意思是由串行开发变为并行开发,之前的一个个类之间相互实例化调用彼此的方法,现在都改为接口,接口有之前类的抽象方法,之前类变为接口的实现类,这样各个类之间就没有了必然的关系,不存在谁调用谁的问题,都是调用接口,再由类去实现接口,大大降低了这个类错了,其他的类也要改的麻烦!

接口与回调:

回调是一种程序设计模式,在这种模式中,可以指出某个特定事件发生时应该采取的动作。

java基础 总结版  java基础 总结版

抽象类与接口的区别:

抽象类可以含有抽象方法和非抽象方法,有构造函数,接口中只能有抽象方法,没有构造函数。抽象类属于类,只能单继承,而接口可以多继承,抽象类比较笨重,而接口很灵活,很方便。但是有限选择类,设计时候用就接口,但是可以实现其工具类。两者的抽象层次不同,抽象类是对类抽象(整体),而接口是对行为的抽象(局部)。

重写:

又叫覆盖,一般用于继承或者实现接口关系中,从父类继承过来的方法不再适用于子类,子类需要对其进行重新定义,

重写的方法名,返回值类型,参数一定要相同。 修饰符相同或者更宽。

静态只能覆盖静态,父类的返回类型若为基本类型时,其子类重写时不能改变返回值类型,若为其他类型,子类重写的方法其返回类型可以是子类。

 

重载

一个类的内部进行的多态,通过相同的方法名,不同的参数名(个数,类型,顺序)。与返回值类型无关

 

关于重写和重载:两者是重写是继承多态相关的,子类继承父类的方法,但是不适用自己的情况,于是对其进行重写,调用时,父类引用指向子类对象,调用的是相应子类对象的方法,重载就是一个类内部的事情,优点是屏蔽使用差异,共同的方法名,但是参数不同,调用该方法时,系统会通过匹配所有的该方法名方法,找到具有相同参数列表的方法,调用它。

多态

概括:父类引用→→→子类对象

前提是继承,没有继承就没有多态,多态就是在父类的方法的基础上,子类继承了父类的方法并重写了它,在方法中可以以父类为形参,具体调用方法的时候依据对象的不同,在选择相应的方法,最后的效果就是 从同一个父类中导出的子类调用同一个父类的方法,可以产生不同的结果。

This和super:

  1. 只能在方法内部使用,表示对“调用方法的那个对象“的引用,如果是在方法内调用同一个类的另一个方法,则不需要使用this,当出现this时,可以替换为此处所处的类实例出来的一个对象,可以使用在构造函数中,构造函数的重载中使用this()可指代其他的构造方法(依据参数),但是构造方法中的this必须在第一行!!!

Super和this的使用差不多,只不过他是指向this的父类对象,注意子类的构造方法第一行自动添加super(),

内部类:

分为局部内部类,成员内部类,静态内部类,匿名内部类

依据内部类在外部类中的位置所判定的。主要是匿名内部类,其实主要就是抽象类和接口的实现,省略的是实现类的创建,但是若所创建的对象之后你还要使用的话不要使用匿名内部类,可使用局部匿名类,对象可以多次使用。

代理:

 

第二部分:集合

整体概括:

java基础 总结版

集合框架:是一个用来代表和操纵集合的统一架构,所有的集合框架都包含 接口,实现类,算法

框架:↓↓↓(接口)

java基础 总结版

(类):java基础 总结版

java基础 总结版

需满足:该框架必须是高性能的,基本集合(动态数组,链表,树,哈希表)的实现也必须是高性能的

              该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性,

              对一个集合的扩展和适应必须是简单的。

容器:分为collection和map

                     Collection又分为list和set

                     Map和collection平级,

List

有序的collection,此接口的用户可以对列表中每个元素的插入位置进行精准的控制,用户可以根据元素的整数索引访问元素,并搜索列表中的元素。列表通常允许重复的元素,listiterator只适用于List,其他的Set,Map并没有这样的方法。

Arraylist:以数组的形式实现,查询快,插入删除慢,不是线程同步的

原因:数组是一块连续的内存空间java基础 总结版

Linkedlist:以链表的形式实现,插入删除快,查询慢,不是线程同步的

原因:链表是一个个独立的空间,将每个对象存放在独立的结点中,每个结点还存放着序列中下一个结点的引用。在java程序设计中,所有的链表都是双向链接的(前驱和后继)。

java基础 总结版

Vector:可以实现可增长的对象数组,大小可以根据需要增大或缩小,是同步的。

java基础 总结版

将List转化为一个int[ ]数组:

Int [ ] array = new int [ list.size()];

For(int I = 0;i<list.size();i++){

Array[i] = list.get[i];

}

将一个数组转化为list集合:

List<intrger> list = new ArrayList<integer>();

For(int I : array){

   List.add(i);

}

Set

一个不包含重复元素的collection,,禁止将自身作为作为元素。

HashSet:实际上就是HashMap的一个实例,详见hashmap。线程不同步

       判断hashCode是否相同,不同就存储,相同再判断equals方法,都相同了不存。

TreeSet:基于TreeMap的NavigableSet实现,使用元素的自然顺序对元素进行排序,线程不同步,底层时二叉树进行的排序。保证元素唯一性的方式就是参考实现接口的compare()方法返回的结果是否为0,为0则不存储。如果没有实现comparator接口则无法进行比较功能,运行时会发生classCastException异常。1.元素自身具备比较功能:元素就要实现Comparable接口,覆盖compare to()方法。2.集合自身具备比较功能:定义一个类实现Comparator接口,覆盖compare()方法,将该类对象作为参数传递给TreeSet集合的构造函数。  

LinkedHashSet:有序,HashSet的子类。

TreeSet以集合自身具备比较功能:

代码:

class Person1{

         String name;

         int age;

         public Person1(String name,int age) {

                   // TODO Auto-generated constructor stub

                   this.name = name;

                   this.age = age;

         }

         @Override

         public String toString() {

                   return "Person1 [name=" + name + ", age=" + age + "]";

         }       

}

 

class ComparatorByName implements Comparator{

         public int compare(Object o1,Object o2){

                   Person1 p1 = (Person1) o1;

                   Person1 p2 = (Person1) o2;

                   int temp = 0;

                   temp =  p1.name.compareTo(p2.name);

                   return temp==0?p1.age-p2.age:temp;

         }

}

public class TreeSetDemo2 {

         public static void main(String[] args) {            

                   TreeSet ts = new TreeSet(new ComparatorByName());

                   ts.add(new Person1("lily",15));

                   ts.add(new Person1("xily",12));

                   ts.add(new Person1("nily",15));

                   ts.add(new Person1("sily",22));

                   Iterator it = ts.iterator();

                   while (it.hasNext()) {

                            Person1 p = (Person1)it.next();

                            System.out.println(p);

                   }

         }

}

TreeSet让元素自身具备比较功能:

代码:

class Person implements Comparable{

         public String name;

         public int age;

         public Person(){}

         public Person(String name, int age) {

                   this.name = name;

                   this.age = age;

         }

         /*public int hashCode() {

                            return name.hashCode()+age*31;

         }

         public boolean equals(Object obj) {

                   if (obj == this)  return true;

                   if (obj==null) return false;

                   if (this.getClass()!=obj.getClass()) return false;

                   Person other = (Person)obj;

                   if(other.name.equals(name)&&other.age==age) return true;

                   return false;

         }*/

         @Override

         public String toString() {

                   return "Person [name=" + name + ", age=" + age + "]";

         }

         /*@Override

         public int hashCode() {

                   final int prime = 31;

                   int result = 1;

                   result = prime * result + age;

                   result = prime * result + ((name == null) ? 0 : name.hashCode());

                   return result;

         }

         @Override

         public boolean equals(Object obj) {

                   if (this == obj)

                            return true;

                   if (obj == null)

                            return false;

                   if (getClass() != obj.getClass())

                            return false;

                   Person other = (Person) obj;

                   if (age != other.age)

                            return false;

                   if (name == null) {

                            if (other.name != null)

                                     return false;

                   } else if (!name.equals(other.name))

                            return false;

                   return true;

         }*/

         @Override

         public int compareTo(Object o) {

                   Person p = (Person) o;

                   int temp = this.age - p.age;

                   return temp == 0 ?this.name.compareTo(p.name):temp;

         }       

}

 

public class TreeSetDemo {

         public static void main(String[] args) {

                   TreeSet ts = new TreeSet();

                   ts.add(new Person("lily",28));

                   ts.add(new Person("lily",15));

                   ts.add(new Person("lily",36));

                   Iterator iterator = ts.iterator();

                   while (iterator.hasNext()) {

                            Person p = (Person)iterator.next();

                            System.out.println(p);

                   }       

         }

}

Map

Map:一次添加一对元素,Collection一次添加一个元素。

Map中存储的就是键值对,map必须保证键的唯一。当set已经存在的键信息时,会替换掉原有的信息。

遍历map的三种方式:

//one

                   //Map.Entry:是一个单独的接口,java.util.Interface Map.Entry<K,V>

                   //将map中的内容进行遍历

                   /*

                    * entry function:

                    * equals(),getClass(),getValue(),getKey(),setValue(),toString()...

                    */

                   for (Map.Entry<String, String> entry : map.entrySet()) {

                            if (entry.getValue().equalsIgnoreCase("Jsp")) {

                                     System.out.println("name:"+entry.getKey());

                            }

                   }

                   //two

                   /*

                    * use map.keySet() function return (a set view of the keys contained in this map)

                    * pass get "key" to use map.get(key) to get value;

                    */

                   Set<String> keySet = map.keySet();

                   for (String key : keySet) {

                            if (key.equalsIgnoreCase("lucy")) {

                                     System.out.println(map.get(key));

                            }

                   }

                   //three

                   /*

                    * use iterator

                    * Iterator:java.util.Interface Iterator<E>

                    * attr: E:  iterator return type

                    * function: hasNext()→if iterator has more element return true

                    *                         next()→return next element

                    *                         remove()→delete this iterator return last element

                    */

//效率高!!!★★★

                   Iterator<Map.Entry<String, String>> it  = map.entrySet().iterator();

                   while (it.hasNext()) {

                            Map.Entry<String, String> entry = it.next();

                            String value = entry.getValue();

                            if (value.equalsIgnoreCase("oracle")) {

                                     System.out.println(entry.getKey());

                            }

                   }

Hashtable:

继承Dictionary类(此类已过时),实现map接口,

Put方法:     1. 判断value是否为空,为空直接抛出异常。

                    2.计算key的hash值,获得在数组中的位置,位置上不为空则迭代,遇到相同的直接替换,否则,插入到相应位置。

遍历:1.table.keys() 2.elements()   3.keyset()       4.entrySet()   

Hashmap和hashtable的比较:

1.继承关系     2.是否允许为空     3.是否同步

集合的遍历:

For循环,foreach循环,和iterator,其中for适用于所有情况,foreach只适用于collection, iterator适用于所有情况,但是listiterator只适用于list。遍历数组型集合的时候尽可能使用整数索引的方法来访问,而遍历链表型集合的时候尽可能的使用iterator迭代器来访问

Foreach()循环时不能对元素进行赋值

★★★可以将iterator.next和InputStream.read看作为等效的。

最有效移除集合元素的方式:iterator.remove()方法。

有关集合的技巧:

看到Array就是数组结构,有角标,查询速度很快。

看到Link就是链表结构,增删速度快,而且有特有方法。

看到hash就是哈希表,想到哈希值,唯一性,存入该结构的元素必须覆盖hashCode,equals。

看到tree就是二叉树,排序,就要对元素或集合实现comparator或comparable接口。

Collections工具类:

addAll

(boolean)

将所有指定元素添加到collection中

binarySearch

(int)

使用二分搜索法获得指定对象

Copy

(void)

将所有元素从一个列表复制到另一个列表

Emptylist(

List)

返回一个空的List

emptySet

 

emptyMap

 

Fill

(void)

使用指定元素替换所有元素

Frequency

(int)

返回collection中等于指定对象的元素数

IndexOfSubList

(int)

第一次出现目标的起始位置

replaceAll

(boolean)

替换列表中出现的所有某一值

Reverse

(void)

反转列表中元素的顺序

Sort

(void)

根据自然顺序对列表中的元素进行升序排序

SynchronizedCollection

返回指定collection支持的同步

 

 

 

 

将数组转化为List集合。Arrays.asList()

集合转化为数组:Collection.toArray()

第三部分:I/O

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或者抽象。IO流用来处理设备之间的数据传输。

分类:

按方向→→→→→→→→输入流,输出流

按操作的数据类型→→→字节流,字符流

java基础 总结版

字符流=字节流+编码表。

读取一个文本文件:

/*第一种:

                    * try {

                            FileReader fr = new FileReader("D:\\cc.txt");

                            int ch = 0;

                            while ((ch = fr.read())!=-1) {

                                     System.out.print((char)ch);

                            }

                   } catch (FileNotFoundException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }*/

                   /*

                    * 第二种:

                   FileReader fr = null;

                   try {

                            fr = new FileReader("D:\\cc.txt");

                            char[] ch = new char[2];

                            int leng = 0;

                            while ((leng=fr.read(ch))!=-1) {

                                     System.out.print(new String(ch)); 

                            }

                   } catch (FileNotFoundException e) {

                   }finally {

                            fr.close();

                   }

                   */

字符流缓冲区:

缓冲区的出现是为了提高对数据的读写效率,缓冲区要结合流才可以使用。在流的基础上对流的功能进行了增强。

缓冲区的使用:

/*

                    * 写入

                   FileWriter fw = new FileWriter("D:\\cc.txt");

                   BufferedWriter bw = new BufferedWriter(fw);

                   for (int i = 0; i < 5; i++) {

                            bw.write("莉莉:"+i);

                            bw.newLine();

                   }

                   bw.close();

                   fw.close();

                   //读取

                   FileReader fr = new FileReader("D:\\cc.txt");

                   BufferedReader br = new BufferedReader(fr);

                   String line = null;

                   while ((line=br.readLine())!=null) {

                            System.out.println(line);

                   }

                   br.close();

                   fr.close();     

                   }

*/

 

字节流及缓冲:

public static void copy_1() throws IOException{

                   FileInputStream fis = null;

                   FileOutputStream fos = null;

                   try {

                            fis = new FileInputStream("D:\\cc.txt");

                            fos = new FileOutputStream("F:\\lily.txt");

                            byte[] by = new byte[10];

                            int leng = 0;

                            while ((leng=fis.read(by))!=-1) {

                                     fos.write(by);

                            }

                   } catch (FileNotFoundException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }finally {

                            fos.close();

                            fis.close();

                   }

         }

         public static void copy_2() throws IOException{

                   FileInputStream fis = null;

                   BufferedInputStream bis = null;

                   FileOutputStream fos = null;

                   BufferedOutputStream bos = null;

                  

                   try {

                            fis = new FileInputStream("D:\\cc.txt");

                            bis = new BufferedInputStream(fis);

                           

                            fos = new FileOutputStream("D:\\dd.txt");

                            bos = new BufferedOutputStream(fos);

                           

                            byte[] by = new byte[10];

                            int leng = 0;

                            while ((leng=bis.read(by))!=-1) {

                                     bos.write(by);

                            }

                   } catch (FileNotFoundException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }finally {

                            bos.close();

                            bis.close();

                   }

         }

对象序列化:

ObjectOutputStream()

              ObjectInputStream()

                     1 增强了缓冲作用

                     2 可以操作8种基本类型

                     3 增强了读写对象的功能

                            write Object(Object obj);     将对象写入文件

                            Object readObject();            从文件读取对象

                           

              对象在流上传输的过程叫做对象序列化

              要求:参与序列化的对象必须实现一个接口:

                            java.io.Serializable

              文件到达尾部的标志:抛出异常:java.io.EOFException

              若参与对象序列化的对象的属性也是对象类型,此对象必须也是可序列化的

              若集合中存储的元素是对象类型,集合参与对象序列化时,储存的元素也必须时刻序列化的

              transient 关键字表示该条属性不参与序列化

              private static final long serialVersionUID = 1L;是序列化对象的标识,如果序列化对象

              在反序列化时添加了属性或者方法,却并没有加入序列id那么会报错

转换流:

字符流和字节流之间的桥梁,方便了字符流和字节流之间的操作。

InoutStreamReader:字节到字符的桥梁

OutputStreamWriter:字符到字节的桥梁

 

关于流的操作规律,通过四个明确即可:

  1. 明确源和目的:InputStream和OutputStream
  2. 明确是否是文本数据源:Reader,Writer和InputStream,OutputStream
  3. 明确具体的设备:File,System.out,数组,Socket流和File,System.out,数组,Socket流
  4. 是否需要其他额外功能,缓冲区

 

File类:

用来将文件或者文件成对象,方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。

 

第四部分:线程

概念:

       多线程:指的是这个程序(一个进程)运行时产生了不止一个线程。

       并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。

       并发:通过cpu调度算法,让用户看上去以为是同时在执行多个任务。

进程和线程一样都分为五个阶段:创建,就绪,运行,阻塞,终止

Thread

Thread线程中的对象是分别独立进行任务的,每个都是一个进程。数据是独立的。

继承Thread类,覆盖run()方法

              class MyThread extends Thread {

                     public void run(){}

              }

              创建线程对象:

                     MyThread mt = new MyThread();

              调用start()方法开启线程

                     mt.start();

Runnable

可以理解为一个进程下的多个线程!数据共享

实现Runnable接口,覆盖run()方法

              class MyThread implements Runnable(){

                     public void run(){}

              }

              创建目标对象

                     MyThread mt = new MyThread();

              创建线程对象

                     Thread t = new Thread(mt);

              调用start()方法开启线程

                     t.start();

线程池

线程池的顶级接口是Executor,但是真正的线程池接口是ExecutorService,因为严格意义上讲Executor并不是一个线程池。

作用:限制系统中执行线程的数量,根据系统的环境情况,可以手动或自动设置线程数量达到运行的最佳效果。还可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用可执行多个任务。

常用的线程池:

  1. newSingleThreadExecutor:创建一个单线程的线程池。
  2. newFixedThreadPool:创建一个固定大小的线程池
  3. newCachedThreadPool:创建一个可缓存的线程池如果线程池的大小,超过了处理任务所需要的线程,那么就会回收部分空闲(60s不执行任务)的线程。不够的话会创建新的线程出来。
  4. newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。

 

 

Callable

Futrue

线程的状态:

       初始状态-->就绪状态-->可运行状态-->运行状态-->终止状态

       初始状态:创建线程对象后,但在调用start方法前的状态

       就绪状态:调用start方法之后但未被CPU分配资源

       可运行:

线程同步:

              1 临界资源:被多个线程共享的对象

              2 原子操作:多步不可分割的操作,其顺序和步骤不可被打破。

              3 线程同步:多线程并发时,为了保证临界资源的正确性,

              而不能破坏程序中的原子操作。

几个方法:

                     sleep(long ms) 让当前线程处于休眠状态,释放cpu但是不会释放锁标记

                     join();加入到自身线程中,让其他线程优先执行。

wait(); 此方法必须使用在该对象的同步代码块中;

                            会让当前线程处于无限期的等待状态

                            会让当前线程释放所拥有的锁标记,同时释放cpu

                     notify();通知一个线程从等待中结束

                     notiyAll();通知所有县城从等待中结束

                            必须使用在该对象的同步代码块zhong

                            通知线程从等待中结束

                            不会让当前线程释放锁标记

第五部分:异常

异常:就是程序在运行时出现不正常情况

Throwable:Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。

       Error:描述了Java运行时系统的内部错误和资源耗尽错误,应用程序不应该抛出这种错误,如果出现了这种错误,除了通报给用户,并尽力使程序安全的终止之外,再也无能为力了。

       Exception:

              Runtimeexception:由程序错误而导致的异常

  1. 错误的类型转换
  2. 数组访问越界
  3. 访问null指针

              其他异常:程序没错,其他情况发生的异常。如io…

  1. 试图在文件尾部后面读取数据
  2. 试图打开一个不存在的文件
  3. 试图根据给定的字符串查找Class对象,而这个字符串表示的类型并不存在

Java将error类和runtimeException类的所有异常称为非受查异常(不用声明,系统错误处理不了,逻辑错误有声明的时间不如修改一下逻辑错误),所有其他的异常称为受查异常。

抛出异常:throw和throws

       当在代码中遇到可能出现的错误情况时就要给其考虑在内,若错误后果不可恢复或者回复很麻烦的情况下,可以通过throw new 异常类()将其抛出,说明此处有错误需要处理,然后通过throws关键字的解决方案解决之后重新返回此处或者进行其他执行。

抛出异常的四种情况:throws声明异常

  1. 调用一个抛出受查异常的方法,例如:FileInputStream构造器。
  2. 程序运行过程中发现错误,并且利用throw语句抛出一个受查异常。
  3. 程序出现错误
  4. Java虚拟机运行时出现内部错误

关于继承中的异常:

       如果子类覆盖了父类的一个方法,子类方法中声明的受查异常不能比父类方法中声明的异常更通用(子类可以抛出更特定的异常或者没有异常)。相反如果父类没有抛出任何异常,子类也不能。

异常的捕获:

Try():用来捕获异常,在这个块中尝试可能产生异常的各种方法调用

Catch():在此处处理捕获的各种异常,而且针对每个要捕获的异常准备相应的处理程序。

Finally():

 

使用异常机制的技巧:

  1. 异常处理不能代替简单的测试
  2. 不要过分的细化异常
  3. 利用异常层次结构
  4. 不要压制异常
  5. 在检测错误时,“苛刻”要比放任好
  6. 不要羞于传递异常

对于异常的处理:终止与恢复

  1. 终止模型:在此模型中将假设错误非常关键,以至于程序无法异常产生的地方继续执行,一旦异常被抛出,就表明错误无法挽回,也不能回来继续执行
  2. 恢复模型:异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次能成功。这种遇到错误时不能抛出,而是调用方法来修正该错误,或者把try()块放在while循环中,直到得到满意的结果。这种方法并不常用,应为会导致耦合。

Error和exception的区别:

       Error属于编译时错误,根本不会编译通过,也就是不会生成.class文件,exception属于运行时错误,只有在调用的时候才会报错,比如空指针异常,数组下标越界…

自定义异常:

 

 

日志:

 

断言:

相关面试题:

  1. 一个“.java”源文件中是否可以包括多个类(不是内部类),有什么限制?

可以有很多类,但是只能有一个public类,源文件名与之相同,不过最好一个“.java”文件只包含一个类。

  1. &&和&的区别?

&&与&是都逻辑与,只有符号两边的表达式都为true时整个式子才为true。

&&另外还具有短路作用,当第一个式子为false的时候此时系统直接判定整个式子为false输出,后面表达式不再判断,可以提高系统效率。

&另外有按位与功能,是二进制之间的运算,按位一个一个与。

  1. Java如何跳出当前的多重其嵌套循环?

使用带标签的break或continue。

  1.