Java复习篇二
从天津转站北京,爬到中关村到直立行走
Java复习篇二
四种形式的的类:
成员式:静态内部类:静态类中的内部类,调用外部类的私有属性和方法。
成员内部类:外部类对象和内部类对象(即外部类对象的引用,1对多的关系)
OuterA outer = new OurterA();
OuterA.InnerB innb = OuterA.new InnerB();
局部式:局部内部类:
匿名内部类
为什么要用内部类:1)某类中访问另外一个类中的私有类。
2)某一个类中的对象依赖于另一个类的对象。
代码部分:
package Javamodel;
/**
* 区分内部类中的成员式:静态内部类和成员内部类的区别
* @author xinglefly
* @version 1
*/
public class InnerClass2 {
public static void main(String [] args){
InnerOut.InnerA innA = new InnerOut.InnerA();
innA.moveA();
InnerOut out = new InnerOut();
InnerOut.InnerB innB = out.new InnerB();
innB.moveB();
}
}
class InnerOut{
private static String str1="hehe";
private String str2="xinglefly";
public static void m1(){
System.out.println("static function");
}
public void m2(){
System.out.println("non-static function");
}
//静态内部类 (静态代码块)
static class InnerA{
private static String str1="static innerA";
private String str2="ineerA str2";
public static void moveA(){
//只能调用外部内的静态变量,不能调用非静态属性
System.out.println(InnerOut.str1);
System.out.println(str1);
InnerOut.m1();
//m2();
}
}
//成员内部类 需要有外部的成员对象才能生成内部的对象
class InnerB{
//内部类对象的引用,1对多的关系
String str1="static innerA";
String str2="ineerA str2";
public void moveB(){
//可以访问外部的所有成员
System.out.println(InnerOut.str1);
System.out.println(InnerOut.this.str2);
m1();
m2();
}
}
}
局部类通过接口的回调
package Javamodel;
/**
* 局部内部类
* @author xinglefly
* @version 1
*/
public class InnerClass3 {
public static void main(String[] args){
OutB outer = new OutB();
MyInter my = outer.outerM();//接口的回调
my.m1();
my.m2();
}
}
class OutB{
String str1="hello";
public MyInter outerM(){
int i=10;
final int j=20;
//局部内部类
class InnerC implements MyInter{
public void m1() {
System.out.println("innerc m1");
}
public void m2() {
System.out.println("innerc m2");
}
}//innerc end
return new InnerC();
}//outerM() end
}
interface MyInter{
public void m1();
public void m2();
}
------------------------------
package Javamodel;
/**
* 匿名内部类:
* @author xinglefly
* @version 1
*/
public class InnerClass4 {
//遵循两个原理:1.定义一个类,实现或者继承MyInter,并按照大括号中的方式实现或者覆盖接口中的方法
//2.生成一个该类的对象,特殊的局部内部类。
public static void main(String[] args){
method(new MyInter(){
public void m1(){
System.out.println("m1()");
}
public void m2(){
System.out.println("m2()");
}
});
}
public static void method(MyInter myi){
myi.m1();
myi.m2();
}
}
class OouterC{
public MyInter outerM(){
return new MyInter(){
public void m1(){
}
public void m2(){
}
};
}//outerM end
}
依照上面内部类的分类继续需要注意事项(由浅入深)
内部类:
(注:所有使用内部类的地方都可以不用内部类,使用内部类可以使程序更加的简洁,便于命名规范和划分层次结构)。
内部类是指在一个外部类的内部再定义一个类。
内部类作为外部类的一个成员,并且依附于外部类而存在的。
内部类可为静态,可用PROTECTED和PRIVATE修饰。(而外部类不可以:外部类只能使用PUBLIC和DEFAULT)。
成员内部类:作为外部类的一个成员存在,与外部类的属性、方法并列。
内部类和外部类的实例变量可以共存。
在内部类中访问实例变量:this.属性
在内部类访问外部类的实例变量:外部类名.this.属性。
成员内部类的优点:
⑴内部类作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为PRIVATE,但是对于处于其内部的内部类还是可见的。)
⑵用内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限。
注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。
对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。
成员内部类不可以有静态属性。(为什么?)
如果在外部类的外部访问内部类,使用out.inner.
建立内部类对象时应注意:
在外部类的内部可以直接使用inner s=new inner();(因为外部类知道inner是哪个类,所以可以生成对象。)
而在外部类的外部,要生成(new)一个内部类对象,需要首先建立一个外部类对象(外部类可用),然后在生成一个内部类对象。
Outer.Inner in=Outer.new.Inner()。
错误的定义方式:
Outer.Inner in=new Outer.Inner()。
注意:当Outer是一个private类时,外部类对于其外部访问是私有的,所以就无法建立外部类对象,进而也无法建立内部类对象。
局部内部类:在方法中定义的内部类称为局部内部类。
与局部变量类似,在局部内部类前不加修饰符public和private,其范围为定义它的代码块。
注意:局部内部类不仅可以访问外部类实例变量,还可以访问外部类的局部变量(但此时要求外部类的局部变量必须为final)??
在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。
要想使用局部内部类时需要生成对象,对象调用方法,在方法中才能调用其局部内部类。
静态内部类:(注意:前三种内部类与变量类似,所以可以对照参考变量)
静态内部类定义在类中,任何方法外,用static定义。
静态内部类只能访问外部类的静态成员。
生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类。
静态内部类不可用private来进行定义。例子:
对于两个类,拥有相同的方法:
匿名内部类(必须掌握):
匿名内部类是一种特殊的局部内部类,它是通过匿名类实现接口。
IA被定义为接口。
IA I=new IA(){};
注:一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类,没有类名,根据多态,我们使用其父类名。
因其为局部内部类,那么局部内部类的所有限制都对其生效。
匿名内部类是唯一一种无构造方法类。
匿名内部类在编译的时候由系统自动起名Out$1.class。
如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。
因匿名内部类无构造方法,所以其使用范围非常的有限。
//数组
1.定义数组;
2.数组实例化;
3.数组赋值;
4.循环访问数组;
int[] arr;声明 并没有非配空间
arr = new int[5];分配空间,new 相当于指向了它的空间
1.声明:int[] arr;
2.实例化:arr = new Int[5];
1.2合并:int[] arr = new int[5];
声明实例化、赋值合并;
int 【】 arr = new int[]{10,20,30,40,50};
int 【】 arr = {10,20,30,40,50};//声明的赋值只有这样放在一行
int arr[];数组必须为空
for(int i = 0;i < arr.length; i++)
-----------------------
int 【】【】 arr;
arr = new int【3】【5】;
arr = new int【3】【】;
arr【0】= new int 【5】;
arr【1】= new int【3】;对象的引用
int 【】【】 arr ={{1,2,3},{4,5},{6,7}};
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
}
}
-----------------------数组的拷贝
System.arraycopy();
int myArray[] ={1,2,3,4,5,6};
int hold[] = {10,9,8,7,6,5,4,3,2,1};
System.arraycopy(myArry,0,hold,0,myArry.length);hold(目标数组名),0{目标数组接收元素的开始位置}myArray.length拷贝的长度
Exception
异常由来:问题就是现实生活中一个具体的食物,也可以通过java的类的形式进行描述,并封装成对象。
对于问题的划分:
两种:一种是要严重问题(Error类)
另一种是严重问题 (Exception)
Exception中有一个特殊的子类异常RuntimeException运行时异常。
如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常,调用者可以不用进行处理。
编辑时被检测的异常。(没有处理,也有抛出没try,编辑失败)
(该异常被标识,代表可以被处理)
运行时不被检测的异常,RuntimeException以其子类。
在编译时,不需要处理,编译器不检查。
该异常发生,建议不处理,让程序停止,对代码进行修正。
Catch代表的处理异常。
问题代码和处理代码相分离。
对于程序可能出现的错误应该做出预案。
例外是程序中所有出乎意料的结果。(关系到系统的健壮性)
JAVA会将所有的错误封装成为一个对象,其根本父类为Throwable。
Throwable有两个子类:Error和Exception。
一个Error对象表示一个程序错误,指的是底层的、低级的、不可恢复的严重错误。此时程序一定会退出,因为已经失去了运行所必须的物理环境。
对于Error错误我们无法进行处理,因为我们是通过程序来应对错误,可是程序已经退出了。
我们可以处理的Throwable对象中只有Exception对象(例外/异常)。
Exception有两个子类:Runtime exception(未检查异常)
非Runtime exception(已检查异常)
(注意:无论是未检查异常还是已检查异常在编译的时候都不会被发现,在编译的过程中检查的是程序的语法错误,而异常是一个运行时程序出错的概念。)
在Exception中,所有的非未检查异常都是已检查异常,没有另外的异常!!
未检查异常是为程序员没有进行必要的检查,因为他的疏忽和错误而引起的异常。一定是属于虚拟机内部的异常(比如空指针)。
应对未检查异常就是养成良好的检查习惯。
已检查异常是不可避免的,对于已检查异常必须实现定义好应对的方法。
已检查异常肯定跨越出了虚拟机的范围。(比如“未找到文件”)
如何处理已检查异常(对于所有的已检查异常都要进行处理):
首先了解异常形成的机制:
当一个方法中有一条语句出现了异常,它就会throw(抛出)一个例外对象,然后后面的语句不会执行返回上一级方法,其上一级方法接受到了例外对象之后,有可能对这个异常进行处理,也可能将这个异常转到它的上一级。
对于接收到的已检查异常有两种处理方式:throws和try方法。
注意:出错的方法有可能是JDK,也可能是程序员写的程序,无论谁写的,抛出一定用throw。
例:public void print() throws Exception.
对于方法a,如果它定义了throws Exception。那么当它调用的方法b返回异常对象时,方法a并不处理,而将这个异常对象向上一级返回,如果所有的方法均不进行处理,返回到主方法,程序中止。(要避免所有的方法都返回的使用方法,因为这样出现一个很小的异常就会令程序中止)。
如果在方法的程序中有一行throw new Exception(),返回错误,那么其后的程序不执行。因为错误返回后,后面的程序肯定没有机会执行,那么JAVA认为以后的程序没有存在的必要。
Throwable:
Exception可以控制的异常
RuntimeException运行时异常
ArithneeticException算术运算错误
ArrayIndexOutofBounds数组索引值错误
ArrayStoreException赋给数组实例错误
ClassCastException类型转换
IntgalArgumentException方法参数传递
NativeArraySizeException声明数组的大小为负值
NullPointException未赋给对象实例的对象
SecurityException违反安全性限制
Error无法控制的错误情况
outofMemoryError
StackOverFlowError
UnknownError
AWTError
ThreadDeath
CheckException外在因素
classNotFoundException程序运行时,找不到所需文件
FileNotFoundException找不到制定文件
InterrupedException运行时中断
IOException输入输出处理错误(网络,文件等)
SqlException数据库处理错误
异常的好处:
将问题进行封装
将正常流程代码和问题代码相分离,方便于阅读。
处理原则:
处理方式有两种,try或throws
调用抛出异常的功能时,抛出几个处理几个,一个try对应多个catch
Catch内需要定义针对性的处理方式,不要简单的定义printStackTrace输出语句。
注意事项:
子类抛出异常必须是父类的异常子类或子集。
如果父类或者接口没有异常抛出,子类覆盖出现异常,只能try,不能抛
关于Throws和throw
Throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。
Throw定义在函数内,用于抛出异常对象,并进行try处理。除RuntimeException除外,如果抛出异常,函数上可以不用声明。
对于try……catch格式:
try {可能出现错误的代码块} catch(exception e){进行处理的代码} ;
对象变量的声明
用这种方法,如果代码正确,那么程序不经过catch语句直接向下运行;
如果代码不正确,则将返回的异常对象和e进行匹配,如果匹配成功,则处理其后面的异常处理代码。(如果用exception来声明e的话,因为exception为所有exception对象的父类,所有肯定匹配成功)。处理完代码后这个例外就完全处理完毕,程序会接着从出现异常的地方向下执行(是从出现异常的地方还是在catch后面呢?利用程序进行验证)。最后程序正常退出。
Try中如果发现错误,即跳出try去匹配catch,那么try后面的语句就不会被执行。
一个try可以跟进多个catch语句,用于处理不同情况。当一个try只能匹配一个catch。
我们可以写多个catch语句,但是不能将父类型的exception的位置写在子类型的excepiton之前,因为这样父类型肯定先于子类型被匹配,所有子类型就成为废话。JAVA编译出错。
在try,catch后还可以再跟一子句finally。其中的代码语句无论如何都会被执行(因为finally子句的这个特性,所以一般将释放资源,关闭连接的语句写在里面)。
如果在程序中书写了检查(抛出)exception但是没有对这个可能出现的检查结果进行处理,那么程序就会报错。
而如果只有处理情况(try)而没有相应的catch子句,则编译还是通不过。
如何知道在编写的程序中会出现例外呢
调用方法,查看API中查看方法中是否有已检查错误。
在编译的过程中看提示信息,然后加上相应的处理。
Exception有一个message属性。在使用catch的时候可以调用:
Catch(IOException e){System.out.println(e.message())};
Catch(IOException e){e.printStackTrace()};
上面这条语句回告诉我们出错类型所历经的过程,在调试的中非常有用。
开发中的两个道理:
①如何控制try的范围:根据操作的连动性和相关性,如果前面的程序代码块抛出的错误影响了后面程序代码的运行,那么这个我们就说这两个程序代码存在关联,应该放在同一个try中。
对已经查出来的例外,有throw(积极)和try catch(消极)两种处理方法。
对于try catch放在能够很好地处理例外的位置(即放在具备对例外进行处理的能力的位置)。如果没有处理能力就继续上抛。
当我们自己定义一个例外类的时候必须使其继承excepiton或者RuntimeException。
Throw是一个语句,用来做抛出例外的功能。
而throws是表示如果下级方法中如果有例外抛出,那么本方法不做处理,继续向上抛出。
Throws后跟的是例外类型。
断言是一种调试工具(assert)
其后跟的是布尔类型的表达式,如果表达式结果为真不影响程序运行。如果为假系统出现低级错误,在屏幕上出现assert信息。
Assert只是用于调试。在产品编译完成后上线assert代码就被删除了。
方法的覆盖中,如果子类的方法抛出的例外是父类方法抛出的例外的父类型,那么编译就会出错:子类无法覆盖父类。
结论:子类方法不可比父类方法抛出更多的例外。子类抛出的例外或者与父类抛出的例外一致,或者是父类抛出例外的子类型。或者子类型不抛出例外。
如果父类型无throws时,子类型也不允许出现throws。此时只能使用try catch。
package com.xinglefly.java.test;
import java.sql.SQLException;
/**
* finally代码块:定义一定执行代码。通常用于关闭资源
* @author xinglefly
* @version 1
*/
class Demo1{
public int div(int i,int j)throws FushuException{
if(j<0)
throw new FushuException("不能为负数");
return i/j;
}
public void method()throws noException{
try{
System.out.println("连接数据库");
System.out.println("数据操作");
}catch(Exception e){
System.out.println("会对数据进行异常处理");
throw new noException("不想说");
}finally{
System.out.println("关闭数据库");
}
}
}
public class Exception2 {
public static void main(String[] args){
Demo1 d = new Demo1();
try{
int x = d.div(4, -1);
System.out.println("x="+x);
d.method();
}catch(Exception e){
System.out.println(e.toString());
return;//return 语句是执行函数,如果执行后返回主函数,不执行over
}finally{
System.out.println("一定会被执行代码");
}
System.out.println("over");
}
}
class FushuException extends Exception{
public FushuException(String msg) {
super(msg);
}
class noException extends Exception{
public noException(String msg) {
super(msg);
}
}
}
-----
package Javamodel;
/**
* 异常就是程序在运行时出现不正常情况
* 异常由来:问题就是现实生活中,一个具体的食物,也可以通过java类的形式进行描述,并封装成对象
* 对于问题的划分:两种:一种是要重问题,一种非严重问题。
* Exception 中有一个特殊的异常RuntimeException运行异常,如果在函数内容抛出该异常,函数上可以不用声明编译一样通过
* 1.编译时被检测的异常
* 2.运行时不被检测异常,RuntimeException以及其子类
* @author xinglefly
* @version 1
*/
class DemoTest{
//如果函数抛出异常,就需要处理异常try catch
int div(int i,int j) throws Exception{//在功能上通过throws关键字声明该功能有可能会显现问题
return i/j;
}
int div1(int i,int j)throws ArithmeticException{
//父类runtimeException
//if(j==0)throw new ArithmeticException("被零整除了");
return i/j;
}
}
class Personp{
public void checkName(String name){
//if(name.equals("lili")){//NullPointerException
if("lili".equals(name)){//name.equals(null)&&name.equals("lili")
System.out.println("yes");
}else{
System.out.println("no");
}
}
}
public class ExceptionTest {
public static void main(String [] aegs){
DemoTest d = new DemoTest();
Personp p = new Personp();
p.checkName(null);
p.checkName("lili");
try{
int x = d.div(4, 0);
System.out.println("x="+x);
}catch(Exception e){//Exception e = new ArithmeticException();多态
//给出预先处理的方式
System.out.println("除数不能为0");
System.out.println(e.getMessage());//by zero
System.out.println(e.toString());//类名 异常信息
e.printStackTrace();//类名 异常信息 错误出处
}finally{
System.out.println("div is over!");
}
}
}