(二)Java基础巩固

Java内存:

JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)

堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
为了更清楚地搞明白发生在运行时数据区里的黑幕,我们来准备2个小道具(2个非常简单的小程序)。

AppMain.java
public class AppMain {
  //运行时, jvm 把appmain的信息都放入方法区
    public static void  main(String[] args) {
    //main 方法本身放入方法区。
    Sample test1 = new Sample( " 测试1 " );  
     //test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面
    Sample test2 = new Sample( " 测试2 " );
    test1.printName();
    test2.printName();
    }
} 

Sample.java
public class Sample{
  //运行时, jvm 把appmain的信息都放入方法区
   private name;     
   //new Sample实例后,name引用放入栈区里,name对象放入堆里
   public Sample(String name){
    this.name = name;
   }
  public void printName(){
  //print方法本身放入 方法区里。
    System.out.println(name);
  }
} 

面向过程:(procedure oriented programming POP)

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;

Java面向对象:(object oriented programming OOP)

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

在类中定义的其实都是成员:

1.成员变量:就是对应事务的属性。2.成员函数:就是对应事物的行为

Java匿名函数:

匿名对象使用方法一:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。

如果对一个对象进行多个成员的调用,就必须给这个对象起个名字。

匿名对象使用方法二:可以将匿名对象作为实际参数进行传递

java中的匿名类有一个倍儿神奇的用法,见下面代码示例:

package contract;
public interface ISay { void sayHello(); }

上面是一个简单的接口,下面是如何使用:

package jimmy;
import contract.ISay;
public class Program {
     public static void main(String[] args) {
         ISay say = new ISay() {          
             public void sayHello() {
                 System.out.println("Hello java!");
             }
         };
     }
}

重载和重写的区别。

override重写覆盖
1、方法名、参数、返回值相同。
2、子类方法不能缩小父类方法的访问权限。
3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
4、存在于父类和子类之间。
5、方法被定义为final不能被重写。

overload重载过载
1、参数类型、个数、顺序至少有一个不相同。
2、不能重载只有返回值不同的方法名。
3、存在于父类和子类、同类中。 

成员变量和局部变量

根据定义变量位置的不同,可以将变量分为成员变量和局部变量

成员变量是在类范围内定义的变量:
成员变量可以分为:成员变量无需显式初始化,系统会自动对其进行默认初始化
      实例属性 (不用static修饰):随着实例属性的存在而存在
      类属性 (static修饰):随着类的存在而存在
局部变量是在一个方法内定义的变量:
局部变量可分为:局部变量除了形参外,都必须显示初始化,也就是要指定一个初始值,否则不能访问。
       形参(形式参数):在整个方法内有效
       方法局部变量 (方法内定义):从定义这个变量开始到方法结束这一段时间内有效
       代码块局部变量 (代码块内定义):从定义这个变量开始到代码块结束这一段时间内有效

实参与形参

java的基本数据类型是传值调用,对象引用类型是传引用。

当传值调用时,改变的是形参的值,并没有改变实参的值,实参的值可以传递给形参,但是,这个传递是单向的,形参不能传递回实参。

当引用调用时,如果参数是对象,无论对对象做了何种操作,都不会改变实参对象的引用,但是如果改变了对象的内容,就会改变实参对象的内容。

2.引用数据类型(引用调用)
传引用,方法体内改变形参引用,不会改变实参的引用,但有可能改变实参对象的属性值。

举两个例子:

1)方法体内改变形参引用,但不会改变实参引用 ,实参值不变

public class TestFun2 {  
public static void testStr(String str){  
str="hello";//型参指向字符串 “hello”  
}  
public static void main(String[] args) {  
String s="1" ;  
TestFun2.testStr(s);  
System.out.println("s="+s); //实参s引用没变,值也不变  
}  
} 执行结果打印:s=1
(2)方法体内,通过引用改变了实际参数对象的内容,注意是“内容”,引用还是不变的。
public class TestFun4 {  
public static void testStringBuffer(StringBuffer sb){  
sb.append("java");//改变了实参的内容  
}  
public static void main(String[] args) {  
StringBuffer sb= new StringBuffer("my ");  
new TestFun4().testStringBuffer(sb);  
System.out.println("sb="+sb.toString());//内容变化了  
}  
}  
执行结果,打印:sb=my Java 。

所以比较参数是String和StringBuffer 的两个例子就会理解什么是“改变实参对象内容”了。

Java中普通代码块,构造代码块,静态代码块区别

1 普通代码块

  //普通代码块:在方法或语句中出现的{}就称为普通代码块。普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行”
public class CodeBlock01{
     public static void main(String[] args){
    {
      int x=3;
          System.out.println("1,普通代码块内的变量x="+x);    
       }
             
       int x=1;
       System.out.println("主方法内的变量x="+x);
    {
          int y=7;
          System.out.println("2,普通代码块内的变量y="+y);    
       }
  } }
     运行结果:1.普通代码块内的变量x=3
        2.主方法内的变量x=1
        3.普通代码块内的变量y=7

2 构造代码块

//构造块:直接在类中定义且没有加static关键字的代码块称为{}构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。
public class CodeBlock02{
    {
    System.out.println("第一代码块");            
    } 
    public CodeBlock02(){
        System.out.println("构造方法");
    }
  {
        System.out.println("第二构造块");
  }
    public static void main(String[] args){
          new CodeBlock02();
          new CodeBlock02();
          new CodeBlock02();      
    }
}

/* 执行结果:

       第一代码块,第二构造块,构造方法
       第一代码块,第二构造块,构造方法

*/

3 静态代码块

//静态代码块:在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。
//如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。
//注意:1 静态代码块不能存在于任何方法体内。2 静态代码块不能直接访问静态实例变量和实例方法,需要通过类的实例对象来访问。
class Code{
    {
      System.out.println("Code的构造块");
    }
    static{
        System.out.println("Code的静态代码块");
        }  
    public Code(){
        System.out.println("Code的构造方法");
        }
    }
public class CodeBlock03{
     {
      System.out.println("CodeBlock03的构造块");    
     }
     static{
        System.out.println("CodeBlock03的静态代码块");
     }  
     public CodeBlock03(){
        System.out.println("CodeBlock03的构造方法");
     }   
      public static void main(String[] args){
        System.out.println("CodeBlock03的主方法");
            new Code();
            new Code();
            new CodeBlock03();
            new CodeBlock03();
      }
    }
/*
CodeBlock03的静态代码块
CodeBlock03的主方法
Code的静态代码块
Code的构造块
Code的构造方法
Code的构造块
Code的构造方法
CodeBlock03的构造块
CodeBlock03的构造方法
CodeBlock03的构造块
CodeBlock03的构造方法
*/

封装:

好处:将变化隔离;便于使用;提高重用性;安全性。
封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。
This:哪个对象调用了this所在的函数,this就代表哪个对象,就是哪个对象的引用。
※:用this调用构造函数,必须定义在构造函数的第一行。因为构造函数是用于初始化的,所以初始化动作一定要执行。否则编译失败
Static:
特点: 1,想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。 
    2,被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。  
    3,静态随着类的加载而加载。而且优先于对象存在。
弊端: 1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。 
    2,静态方法只能访问静态成员,不可以访问非静态成员。 因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。 
    3,静态方法中不能使用this,super关键字。 因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。 
    4,主函数是静态的。  
成员变量和静态变量的区别: 
1,成员变量所属于对象。所以也称为实例变量。 静态变量所属于类。所以也称为类变量。 
2,成员变量存在于堆内存中。 静态变量存在于方法区中。 
3,成员变量随着对象创建而存在。随着对象被回收而消失。 静态变量随着类的加载而存在。随着类的消失而消失。 
4,成员变量只能被对象所调用 。 静态变量可以被对象调用,也可以被类名调用。 所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。  
静态的注意:静态的生命周期很长。 
静态代码块:就是一个有静态关键字标示的一个代码块区域。定义在类中。 
作用:可以完成类的初始化。静态代码块随着类的加载而执行,而且只执行一次(new 多个对象就只执行一次)。如果和主函数在同一类中,优先于主函数执行

Java23中设计模式:

总体来说设计模式分为三大类:

创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

 单例模式:

 1):将采用单例设计模式的类的构造方法私有化(采用private修饰)。

 2):在其内部产生该类的实例化对象,并将其封装成private static类型。

 3):定义一个静态方法返回该类的实例

/** 
 * 方法一
 * 单例模式的实现:饿汉式,线程安全 但效率比较低 
 */  
public class SingletonTest {  
    // 定义一个私有的构造方法
    private SingletonTest() {}  
    // 将自身的实例对象设置为一个属性,并加上Static和final修饰符
    private static final SingletonTest instance = new SingletonTest();  
    // 静态方法返回该类的实例
    public static SingletonTest getInstancei() {  
        return instance;  
    }  
}

/**  
 *方法二
 * 单例模式的实现:饱汉式,非线程安全   
 *   
 */  
public class SingletonTest {
    // 定义私有构造方法(防止通过 new SingletonTest()去实例化)
    private SingletonTest() { }   
    // 定义一个SingletonTest类型的变量(不初始化,注意这里没有使用final关键字)
    private static SingletonTest instance;   
    // 定义一个静态的方法(调用时再初始化SingletonTest,但是多线程访问时,可能造成重复初始化问题)
    public static SingletonTest getInstance() {   
        if (instance == null)   
            instance = new SingletonTest();   
        return instance;   
    }   
} 
/**  
 * 方法三
 * 单例模式最优方案
 * 线程安全  并且效率高  
 *  
 */  
public class SingletonTest { 
    // 定义一个私有构造方法
    private SingletonTest() {}   
    //定义一个静态私有变量(不初始化,不使用final关键字,使用volatile保证了多线程访问时instance变量的可见性,避免了instance初始化时其他变量属性还没赋值完时,被另外线程调用)
    private static volatile SingletonTest instance;  
    //定义一个共有的静态方法,返回该类型实例
    public static SingletonTest getIstance() { 
    // 对象实例化时与否判断(不使用同步代码块,instance不等于null时,直接返回对象,提高运行效率)
        if (instance == null) {
    //同步代码块(对象未初始化时,使用同步代码块,保证多线程访问时对象在第一次创建后,不再重复被创建)
            synchronized (SingletonTest.class) {
                //未初始化,则初始instance变量
                if (instance == null) {
                    instance = new SingletonTest();   
                }   
            }   
        }   
        return instance;   
    }   
}

(面向对象特征之一) 

好处:

1:提高了代码的复用性。 

2:让类与类之间产生了关系,提供了另一个特征多态的前提

如果想要调用父类中的属性值,需要使用一个关键字:super  

This代表是本类类型的对象引用。

Super代表是子类所属的父类中的内存空间引用。

注意:子父类中通常是不会出现同名成员变量的,因为父类中只要定义了,子类就不用在定义了,直接继承过来用就可以了。

注意:

子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();  

如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数。

如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数 

问题:

super()和this()是否可以同时出现的构造函数中。

两个语句只能有一个定义在第一行,所以只能出现其中一个。

super()或者this():为什么一定要定义在第一行?

因为super()或者this()都是调用构造函数,构造函数用于初始化,所以初始化的动作要先完成。

抽象类:abstract 

抽象:

不具体,看不明白。抽象类表象体现。在不断抽取过程中,将共性内容中的方法声明抽取,但是方法不一样,没有抽取,这时抽取到的方法,并不具体,需要被指定关键字abstract所标示,声明为抽象方法。抽象方法所在类一定要标示为抽象类,也就是说该类需要被abstract关键字所修饰。

抽象类的特点:

1:抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。

2:抽象方法只定义方法声明,并不定义方法实现。

3:抽象类不可以被创建对象(实例化)。

4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。

抽象类的细节

1:抽象类中是否有构造函数?

有,用于给子类对象进行初始化。

2:抽象类中是否可以定义非抽象方法?

可以。其实,抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。

3:抽象关键字abstract和哪些不可以共存?

final , private , static  

4:抽象类中可不可以不定义抽象方法?

可以。抽象方法目的仅仅为了不让该类创建对象。

接 口:

1:是用关键字interface定义的。 
2:接口中包含的成员,最常见的有全局常量、抽象方法。 
注意:接口中的成员都有固定的修饰符。  
成员变量:public static final   
成员方法:public abstract  
interface Inter{
    public static final int x = 3;  
    public abstract void show(); 
} 
3:接口中有抽象方法,说明接口不可以实例化。接口的子类必须实现了接口中所有的抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。 
4:类与类之间存在着继承关系,类与接口中间存在的是实现关系。  继承用extends  ;实现用implements ; 
5:接口和类不一样的地方,就是,接口可以被多实现,这就是多继承改良后的结果。java将多继承机制通过多现实来体现。  
6:一个类在继承另一个类的同时,还可以实现多个接口。所以接口的出现避免了单继承的局限性。还可以将类进行功能的扩展。 
7:其实java中是有多继承的。接口与接口之间存在着继承关系,接口可以多继承接口。  
 
接口都用于设计上,设计上的特点:(可以理解主板上提供的接口) 
1:接口是对外提供的规则。 
2:接口是功能的扩展。 
3:接口的出现降低了耦合性。  
 
抽象类与接口: 
抽象类:一般用于描述一个体系单元,将一组共性内容进行抽取,
特点:可以在类中定义抽象内容让子类实现,可以定义非抽象内容让子类直接使用。它里面定义的都是一些体系中的基本内容。 
接口:一般用于定义对象的扩展功能,是在继承之外还需这个对象具备的一些功能。  抽象类和接口的共性:都是不断向上抽取的结果。  
 
抽象类和接口的区别: 
1:抽象类只能被继承,而且只能单继承。 接口需要被实现,而且可以多实现。  
2:抽象类中可以定义非抽象方法,子类可以直接继承使用。 接口中都有抽象方法,需要子类去实现。 
3:抽象类使用的是is a关系。 接口使用的like a关系。  
4:抽象类的成员修饰符可以自定义。 接口中的成员修饰符是固定的。全都是public的。  
在开发之前,先定义规则,A和B分别开发,A负责实现这个规则,B负责使用这个规则。至于A是如何对规则具体实现的,B是不需要知道的。这样这个接口的出现就降低了A和B直接耦合性。 

多态:

父类引用或者接口的引用指向了自己的子类对象。//Animal a = new Cat(); 
多态的好处:提高了程序的扩展性。 
多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。(前期不能使用后期产生的功能,即访问的局限性) 

多态在子父类中的成员上的体现的特点: 

1,成员变量
成员变量:在多态中,子父类成员变量同名。  
在编译时期:参考的是引用型变量所属的类中是否有调用的成员。(编译时不产生对象,只检查语法错误)  
运行时期:也是参考引用型变量所属的类中是否有调用的成员。  
简单一句话:无论编译和运行,成员变量参考的都是引用变量所属的类中的成员变量。  
再说的更容易记忆一些:成员变量 --- 编译运行都看 = 左边。 
2,成员函数。  
编译时期:参考引用型变量所属的类中是否有调用的方法。  
运行事情:参考的是对象所属的类中是否有调用的方法。  
为什么是这样的呢?因为在子父类中,对于一模一样的成员函数,有一个特性:覆盖。  
简单一句:成员函数,编译看引用型变量所属的类,运行看对象所属的类。  
更简单:成员函数 --- 编译看 = 左边,运行看 = 右边。
3,静态函数。   
编译时期:参考的是引用型变量所属的类中是否有调用的成员。  
运行时期:也是参考引用型变量所属的类中是否有调用的成员。  
为什么是这样的呢?因为静态方法,其实不所属于对象,而是所属于该方法所在的类。  
调用静态的方法引用是哪个类的引用调用的就是哪个类中的静态方法。 
简单说:静态函数 --- 编译运行都看 = 左边。 

Object

所有类的直接或者间接父类,Java认为所有的对象都具备一些基本的共性内容,这些内容可以不断的向上抽取,
最终就抽取到了一个最顶层的类中的,该类中定义的就是所有对象都具备的功能。   
1boolean equals(Object obj)用于比较两个对象是否相等,其实内部比较的就是两个对象地址。 
而根据对象的属性不同,判断对象是否相同的具体内容也不一样。所以在定义类时,一般都会复写equals法,建立本类特有的判断对象是否相同的依据。  
public boolean equals(Object obj){   
    if(!(obj instanceof Person))    
        return false;   
    Person p = (Person)obj; 
        return this.age == p.age;  
}
2String toString()
将对象变成字符串;默认返回的格式:类名@哈希值 = getClass().getName() '@' + Integer.toHexString(hashCode())  
为了对象对应的字符串内容有意义,可以通过复写,建立该类对象自己特有的字符串表现形式。   
public String toString(){   
    return "person : "+age;  
}
3Class getClass()获取任意对象运行时的所属字节码文件对象。 
4int hashCode()返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。  
通常equalstoStringhashCode,在应用中都会被复写,建立具体对象的特有的内容
 
匿名内部类:没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。
想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。  
匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。  
匿名内部类的使用场景: 当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。 
其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。
new Object(){    
  void show(){
    System.out.println("show run");        
  }   
}.show();   
Object obj = new Object(){
  void show(){     
    System.out.println("show run");    
  }  
};obj.show();    
1和2的写法正确吗?有区别吗?说出原因。   
写法是正确,1和2都是在通过匿名内部类建立一个Object类的子类对象区别:   
第一个可是编译通过,并运行。   
第二个编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了   
Object类型,而编译时检查Object类中是否有show方法,所以编译失败。 
class InnerClassDemo6 {
    +(staticclass Inner{
        void show(){}  
    }  
public void method(){
    this.new Inner().show();//可以  
    }  
public static void main(String[] args) {
    //static不允许this   
    This.new Inner().show();//错误,Inner类需要定义成static
     } 
} 
interface Inter{
    void show(); 
}  
class Outer{
    //通过匿名内部类补足Outer类中的代码。  
public static Inter method(){   
    return new Inter(){
        public void show(){}   
        };  
    } 
}  
class InnerClassDemo7 {  
    public static void main(String[] args) { 
    Outer.method().show();     
/*Outer.method():意思是:Outer中有一个名称为method的方法,而且这个方法是静态的。
    Outer.method().show():当Outer类调用静态的method方法运算结束后的结果又调用了show方法,
    意味着:method()方法运算完一个是对象,而且这个对象是Inter类型的。
*/
function (new Inter(){ public void show(){}
});
//匿名内部类作为方法的参数进行传递。 public static void function(Inter in){ in.show();   } }

异常:

throw 和throws关键字的区别: 
throw用于抛出异常对象,后面跟的是异常对象;throw用在函数内。 
throws用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。throws用在函数上。
 
编译时被检查的异常和运行时异常的区别: 
编译被检查的异常在函数内被抛出,函数必须要声明,否编译失败。 
声明的原因:是需要调用者对该异常进行处理。 
运行时异常如果在函数内被抛出,在函数上不需要声明。 
不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续运行,所以,不让调用处理的,直接让程序停止,由调用者对代码进行修正。  
 
定义异常处理时,什么时候定义try,什么时候定义throws呢? 
功能内部如果出现异常,如果内部可以处理,就用try; 如果功能内部处理不了,就必须声明出来,让调用者处理。 
自定义异常的步骤: 
1:定义一个子类继承Exception或RuntimeException,让该类具备可抛性。 
2:通过throw 或者throws进行操作。  
异常的转换思想:当出现的异常是调用者处理不了的,就需要将此异常转换为一个调用者可以处理的异常抛出。
 
当异常出现后,在子父类进行覆盖时,有了一些新的特点: 
1:当子类覆盖父类的方法时,如果父类的方法抛出了异常,那么子类的方法要么不抛出异常要么抛出父类异常或者该异常的子类,不能抛出其他异常。 
2:如果父类抛出了多个异常,那么子类在覆盖时只能抛出父类的异常的子集。  
注意: 
如果父类或者接口中的方法没有抛出过异常,那么子类是不可以抛出异常的,如果子类的覆盖的方法中出现了异常,只能try不能throws。 
如果这个异常子类无法处理,已经影响了子类方法的具体运算,这时可以在子类方法中,通过throw抛出RuntimeException异常或者其子类,
这样,子类的方法上是不需要throws声明的。  
常见异常: 
1、脚标越界异常(IndexOutOfBoundsException)包括数组、字符串; 空指针异常(NullPointerException) 
2、类型转换异常:ClassCastException 
3、没有这个元素异常:NullPointerException 
4、不支持操作异常; 
异常要尽量避免,如果避免不了,需要预先给出处理方式。比如家庭备药,比如灭火器。

包:定义包用package关键字。 

1:对类文件进行分类管理。 
2:给类文件提供多层名称空间。  
如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中即可。 一般在定义包名时,
因为包的出现是为了区分重名的类。所以包名要尽量唯一。怎么保证唯一性呢?可以使用url域名来进行包名称的定义。 
package pack;//定义了一个包,名称为pack。注意:包名的写法规范:所有字母都小写。 
//package cn.itcast.pack.demo;  
类的全名称是 包名.类名     
编译命令:javac –d 位置(.当前路径) java源文件 (就可以自动生成包)  
包是一种封装形式,用于封装类,想要被包以外的程序访问,
该类必须public; 类中的成员,如果被包以外访问,也必须public;  
包与包之间访问可以使用的权限有两种: 
1:public  
2:protected:只能是不同包中的子类可以使用的权限。  
 Import - 导入:类名称变长,写起来很麻烦。为了简化,
使用了一个关键字:import,可以使用这个关键字导入指定包中的类。
记住:实际开发时,到的哪个类就导入哪个类,不建议使用*. 
import packa.*;//这个仅仅是导入了packa当前目录下的所有的类。不包含子包。 
import packa.abc.*;//导入了packa包中的子包abc下的当前的所有类。  
如果导入的两个包中存在着相同名称的类。这时如果用到该类,必须在代码中指定包名。  
 
常见的软件包: 
java.lang : language java的核心包,Object System  String Throwable jdk1.2版本后,该包中的类自动被导入。 
java.awt : 定义的都是用于java图形界面开发的对象。 
javax.swing: 提供所有的windows桌面应用程序包括的控件,比如:Frame , Dialog, Table, List 等等,就是java的图形界面库。 
java.net : 用于java网络编程方面的对象都在该包中。 
java.io : input  output 用于操作设备上数据的对象都在该包中。比如:读取硬盘数据,往硬盘写入数据。 
java.util : java的工具包,时间对象,集合框架。 
java.applet: application+let 客户端java小程序。server+let  -->  servlet 服务端java小程序。  
jar :java的压缩包,主要用于存储类文件,或者配置文件等。 
命令格式:jar –cf 包名.jar 包目录    
解压缩:jar –xvf 包名.jar   
将jar包目录列表重定向到一个文件中:jar –tf 包名.jar >c:1.txt
原文地址:https://www.cnblogs.com/Jonecmnn/p/6370994.html