Java笔记(一)

1 static关键字---静态变量

1.1 什么时候定义静态变量呢?

当该成员变量的值,每一个对象都一致时,就对该成员变量进行静态修饰。

1.2 静态变量和成员变量的区别:

  • 所属范围不同:静态变量所属类,成员变量所属对象;静态变量亦称类变量,成员变量亦称实例变量;
  • 调用不同:静态变量可以被对象和类调用;成员变量只能被对象调用;
  • 加载时期不同:静态变量随类的加载而加载,成员变量随着对象的加载而加载;
  • 内存存储区域不同:静态变量存储在方法区中,成员变量存储在对内存中。
 Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
 
public Circle
{
    
private double radius;
    
private static double pi = 3.14;//每一个圆对象中都存储一份,浪费内存空间,实现对象的共享,就要加入静态关键字修饰
    Circle(double radius)
    {
        
this.radius = radius;
    }
    
double getArea()
    {
        
return radius*radius*pi;
    }
}

1.3 静态代码块

 主要是了解加载顺序

静态代码块:

特点:随着类的加载而执行,仅执行一次。

作用:给类进行初始化;

静态变量有两次初始化,一次默认初始化,一次是显示初始化,而静态代码块是在静态变量的显示初始化以后执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
class Demo
{
    
static int x = 9;
    
static //静态代码块
    {
        System.out.println(
"类加载执行..."+x);
    }
    
static void show()
    {
        
static void show()
        {
            System.out.println(
"show run");
        }
    }
}
class staticCodeDemo
{
    
public static void main(String[] args)
    {
        Demo show();
        Demo show();
    }
}
/*输出
类加载执行...+9
show run
show run*/

 1.4 构造代码块和局部代码块

构造代码块--只要创建对象就会被调用,给所有对象初始化,构造函数只给对应的对象针对性的初始化。在构造代码块中,可以定义不同构造函数的共性代码。

成员变量默认初始化和显示初始化。 构造代码块是在成员变量显示初始化后执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
class Demo
{
    {
        
//构造代码块
        System.out.println("code run");
    }
    Demo()
    {
        System.out.println(
"demo run");
    }
    Demo(
int x)
    {
        System.out.println(
"demo run"+x);
    }
}

局部代码块,可以控制局部变量的生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
 
class ConstructCodeDemo
{
    
public static void main(String[] args)
    {
        
new Demo();
        {
            
//局部代码块,作用:就可以控制局部变量的生命周期
            int x = 5;
            System.out.println(
"局部代码块..."+x);
        }
        System.out.println(
"over..."+x);//错误,x找不到
    }
}

 2  面向对象--对象的创建过程

  1. 加载Demo.class文件进方法区,并进行空间分配;
  2. 如果有静态变量,先默认初始化,显示初始化;
  3. 如果有静态代码块,要执行仅一次
  4. 通过对对象中的属性进行默认初始化;
  5. 构造函数内部:调用父类构造函数super(),成员变量显示初始化,构造代码块显示初始化,构造函数内容自定义初始化
  6. 对象的初始完毕后,将地址赋值给D。

3 设计模式--单例模式

3.1 单例模式

  • 单例模式 :保证一个类的对象唯一性。比如多个程序要使用一个配置文件的数据,而且要实现数据共享和交换,必须将多个数据封装到同一个对象,而且多个程序操作的是同一个对象。
  • 思路:一个类只要有构造函数,就可以产生多个对象。只要保证其他程序不建立对象即可。自己在本类中创建对象,供其他程序访问。
  • 结果:构造函数私有化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
//---饿汉式
class Single
{
    
//创建一个本类对象
    static Single s = new Single;
    
//私有化构造函数
    private Single();
    
public static Single getIntance()
    {
        
return s;//静态函数只能访问静态成员
    }
}
class SingleDemo
{
    
public static void main(String[] args)
    {
        
//要想获取Single的对象,就要调用getIntance(),因为私有构造函数不可以用对象调用,只能用类对象调用且成员函数必须私有。
        Single ss = Single.getIntance();
        Single ss2 = Single.getIntance();
        
        
//以下方法可以但不建议。加入方法便于可控
        Single ss3 = Single.s;
        Single ss4 = Single.s;
    }
}


//单例模式的延迟加载方式--懒汉式
class Single
{
    
private static Single s = null;
    
//私有化构造函数
    private Single();
    
public static Single getIntance()
    {
        
if(s == null)
            s = 
new Single();//只有调用才会创建对象
        return s;
    }
}

3.2 单例模式继承

为了提高复用,只建立一份代码。一个类只要和另一个产生关系就可以。

关系:继承。

解决:找到两者的共性类型,将需要提供复用的代码进行抽取,定义到一个共性类型的类中。

面向对象的另一个特征:继承

好处:提高代码的复用性,让类与类产生了关系。给另一个特征:多态,提供了前提

在JAVA中继承的体现:java中允许单继承,不支持多继承。

单继承:一个子类只能有一个父类;

多继承:一个子类可以又多个父类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
class Person
{
    
String name;
    
int age;    
}
class Student extends Person
{
    
void study()
    {
        System.out.println(
"good good study");
    }
}
class Worker extends Person
{
    
void work()
    {
        System.out.println(
"hard work");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
//多重继承
class A
{}
class B extends A
{}
class C extends A
{}
//多继承---JAVA中不存在该机制。因为可能存在不确定性因素
class A
{}
class B
{}
class C extends A,B
{}

 4 继承

4.1 继承中成员变量

 成员变量 特殊情况:

1、子类不允许直接访问父类的私有成员变量;

2、子父类中定义了相同名字的成员变量,都存在子类对象中,则应该如下操作:

用this来访问子类的成员变量,(因为先找局部内部的变量,找不到再向外找);

用super来访问父类的成员变量。(因为子类继承父类之后,会在子类中有一个父类的引用super)

 this和super区别: this代表是本类的对象的引用,可以单独输出this地址;但是super代表的是父类的内存空间,不可以单独输出其地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
//父类
class Fu
{
    
/*private int num1 = 3;*///父类中私有的内容子类不可以直接访问
    int num = 3;
}
class Zi extends Fu
{
    
int num = 4;
    
void show()
    {
        System.out.println(
"子类num"+this.num);
        System.out.println(
"父类num"+super.num);
    }
}
class  ExtendsDemo
{
    
public static void main(String[] args) 
    {
        Zi z = 
new Zi();
        z.show();
    }
}

 4.2 继承中的成员函数

特殊情况:

子父类中定义了相同名字的函数,结果是子类的函数在运行。

这种情况在子父类中,是函数的一个特性:override(重写覆盖,复写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
//父类
class Fu
{
    
void show()
    {
        System.out.println(
"fu show run");
    }
}
class Zi extends Fu
{
    
void show()
    {
        System.out.println(
"zi show run");
    }
}
class  ExtendsDemo
{
    
public static void main(String[] args) 
    {
        Zi z = 
new Zi();
        z.show();
      //结果是zi show run
    }
}

 重写什么时候用? 

 重写的注意事项: 

1、子类覆盖父类,必须保证全要大于或者等于父类的权限;

2、静态覆盖静态

3、写法上要一致:函数的返回值类型,函数名,参数列表

 4.3 继承-----构造函数

子父类中构造函数的特点:

当子父类都有构造函数时,执行顺序:

先执行了父类的构造函数,在执行子类的构造函数;

因为子类的所有的构造函数中的第一行都有一句隐式语句super();//默认调用父类中的空参数的构造函数;;

 子类中的构造函数为什么有一句隐式super()呢? 

原因:子类会继承父类的内容,所以子类在初始化,必须先到父类中去执行父类的初始化动作。当父类中没有

空参数构造函数时,子类的构造函数必须同时显示的super语句指定要访问的父类中的构造函数。

 细节: 

1、如果子类的构造函数第一行写了this调用了本类其他构造函数,那么super调用父类的语句还有吗?

没有的,因为this()或者super()只能定义在构造函数的第一行,因为初始化动作要先执行

2、只要构造函数默认第一行都是super(),因而父类的构造函数也是有的。Java体系在设计中,定义了一个所有对象的父类

object。它是类层次结构的根类。

 总结: 

类中的构造函数默认第一行都有隐式的Super()语法,在访问父类中的构造函数,所以父类的构造函数既可以给自己的对象初始化,

也可以给自己的子类对象初始化。

如果默认的隐式super的语句没有对应的构造函数,必须在构造函数在通过this后者super的形式明确调用的构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
class ExtendsDemo3
{
    
public static void main(String[] args) 
    {
        
new Zi();
        
new Zi(6);
    }
}
class Fu
{
    Fu()
    {
        System.out.println(
"Fu constructor run...");
    }
    Fu(
int x)
    {
        System.out.println(
"Fu constructor run..."+x);
    }
}
class Zi extends Fu
{
    Zi()
    {
        System.out.println(
"Zi constructor run...");
    }

    
//super();
    Zi(int x)
    {
        System.out.println(
"Zi constructor run..."+x);
    }
}

  什么时候用super调用父类中的构造函数。 

只要使用父类的制定初始化动作,就在子类中通过super(参数列表)格式化调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
class Person
{
    
private String name;
    
private int age;
    
public Person(String name, age)
    {
        
this.name = name;
        
this.age = age;
    }
    
public void setName(String name)
    {
        
this.name = name;
    }
    
public void getName()
    {
        
return name;
    }
    
public void setAge(int age)
    {
        
this.age = age;
    }
    
public void getAge()
    {
        
return age;
    }
}
class Student extends Person
{
    
public Student(String name, int age)
    {
        
super(name, age);
    }
}
class Worker extends Person
{
    
public Worker(String name, int age)
    {
        
super(name, age);  //必须明确super,否在会有不带参数的super,则父类没有不带参数的构造函数
    }
}

  继承的优点和缺点 

 优点  
新的实现很容易,因为大部分是继承而来的 
很容易修改和扩展已有的实现 
 缺点  
打破了封装,因为基类向子类暴露了实现细节 
白盒重用,因为基类的内部细节通常对子类是可见的 
当父类的实现改变时可能要相应的对子类做出改变 
不能在运行时改变由父类继承来的实现 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
class Fu
{
    
private void Sector(){};
//父类的实现改变,都会改变子类,且私有函数被暴漏
    
public void show()
    {
        Sector();
    }
}
class Zi extends Fu
{
    
//重写
    public void show()
    {
        System.out.println(
"haha");
    }
}

4.4 禁止继承-final关键字

【final关键字】是一个修饰符,可以修饰类,方法,变量(成员变量,局部变量,静态变量)

 【特点】

  1. final修饰的类是一个最终类,不可以再派生;如果类中从出现部分可以重写,部分不可以重写,就用最终化解决;
  2. final修饰的方法是最终方法,不可以重写;
  3. final修饰的变量是一个常量,只能被赋值一次;【只有当变量在程序中不被修改时,加上final修饰,增强阅读性】,final后面的变量必须用大写格式,或者多个词下划线隔开

5 抽象类

5.1 抽象类的细节问题

 细节问题 

1、抽象类一定是父类,不断的衍生子类;

2、抽象有构造函数但是不可以创建对象,虽然不能给自己的对象初始化,但是可以给子类对象初始化;

3、抽象类可以定义抽象方法,也可以为了不让该类创建对象而不定义抽象方法;

4、抽象关键字不可以和哪些关键字共存。 

final -- private -- static 

final修饰的类不可能再产生子类,而抽象类必须有子类;

private修饰的抽象方法是无法被子类覆盖的,而抽象方法是要子类进行覆盖的;

static能够直接被类名直接调用,而抽象方法是不可以直接被类名直接调用的;

 5.2 面向对象--接口---定义与实现

当一个抽象类中的方法都是抽象的,则可以用接口来表示。

接口中的成员被限定为固定几种:

1、定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也成为常量;

2、定义方法,也要有固定修饰符;public abstract,

接口中的成员都是公共的。

【接口的特点】

1、接口不可以创建对象;

2、子类必须覆盖掉接口中所有的抽象方法,子类才可以实例化;否则子类是一个抽象类;

【总结】定义子类去覆盖接口中的方法,子类必须和接口产生关系,类与类的关系是继承,类与接口之间的关系是实现。通过关键字implements

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
interface Demo//定义一个名称为Demo接口
{
    
public static final int NUM = 2;
    
public abstact void show1();
    
public abstact void show2();
}
class DemoImpl implements Demo
{
    
//重写接口中的方法
    public void show1(){}
    
public void show2(){}

}
class InterfaceDemo
{
    
public static void main(String[] args)
    {
        DemoImpl d = 
new DemoImpl;
        d.show1();
        d.show2();
    }
}

 5.3 接口--多实现

【接口的体现】

解决多继承的弊端(当多个父类中有相同功能时,子类调用会产生不确定性)

---原因:在于多继承父类中功能主体,而导致调用运行时,不确定运行哪个主体内容。

解决方法:-将多继承这种机制在java中通过多实现完成的。(原因,因为接口中的功能都没有方法体,由子类来明确。)

1
2
3
4
5
6
7
8
9
10
11
12
 
interface A
{
    
void show();
}
interface B
{
    
void show();
}
class C implements A,B;//多实现,同时实现多个接口
{
    
public void show(){};
}

 5.4 继承--同时多实现

 【接口拓展】子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。如果子类想要继续拓展其他类中的功能,则可以通过实现接口来完成。(接口的出现了避免了单继承的局限性)

接口的出现避免了单继承的局限性,父类中定义的事物的基本功能,接口中定义的事物拓展功能。

1
2
3
4
5
6
7
8
9
 
interface Inter
{
    
public void show();

}
class Zi extends Fu implents Inter
{

}

 【接口出现后的一些小细节】

1、类与类之间就是继承(is a )关系,类与接口之间是实现(like a)关系

接口与接口之间是继承关系,而且可以多继承。

5.5 没有抽象方法的抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
interface Inter
{
    
public void show1();
    
public void show2();
    
public void show3();
    
public void show4();
}
//定义子类,要使用第一种显示方式
//这个类创建对象就不需要,直接将其抽象化
这就是没有抽象方法的抽象类
abstract class InterImpl implements Inter
{
    
//覆盖show1()方法;
    public void show1(){}
    
//为了让该类实例化,还需要覆盖其他三个方法,虽然该类用不上
    public void show2(){}
    
public void show3(){}
    
public void show4(){}
}
//出现问题:为了使用接口中的部分方法,而覆盖了全部方法,而且每一个子类都要这么做,复用性差。
//解决方法:将这些不用的方法单独抽取到一个独立的类中,让这个类去实现接口,并覆盖接口中的所有方法。如下程序所示
//如果有子类去使用显示1方法,让子类继承InterImpl实现类就可以。

//如果有子类去使用显示1方法,让子类继承InterImpl实现类就可以了
class InterImpl11 entends InterImpl
{
    
public void show1()
    {
        System.out.println(
"show1 run");
    }
}
class InterImpl22 entends InterImpl
{
    
public void show2()
    {
        System.out.println(
"show2 run");
    }
}

 6 面向对象---接口

6.1 接口和抽象的区别

类负责描述的是事物的基本功能,接口负责描述事物的扩展功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
class 犬
{
    
public void 吼叫();
    
public void 吃饭();
}
interface 缉毒able
{
    
public abstract void 缉毒();
}
class 缉毒犬 extends 犬 implements 缉毒able
{
    
public void 吼叫(){}
    
public void 吃饭(){}
    
public void 缉毒(){}
}

 总结:

1】抽象类是描述事物的基本功能,可以定义非抽象的方法;接口中定义只能是抽象方法;

2】类与类之间是继承的关系,而类与接口之间是实现关系 like a关系。

6.2  多态好处和缺点

 多态:【体现】父类的引用或者接口的引用指向了自己的子类对象;

1 Dog d = new Dog();//Dog对象的类型是Dog类型。
2 Animal a = new Dog();//Dog对象的类型右边是Dog类型,左边是Animal类型

好多:提高了程序的扩性‘

弊端:通过父类引用操作子类对象,只能使用父类中已有的方法,不能操作子类持有的方法。

前提:

1、必须有关系:继承,实现;

2、通常都有重写操作;

【子类的特有方法如何调用?】

 Animal a = new Dog(); //Animal是父类型,new Dog是子对象。但是父类型引用指向子类对象时,这就是让子类对象进行了类型的提升(向上转型),好处就是提高了扩展性,隐藏子类型。弊端:不能使用子类型的特有方法。

解决弊端方法:如果想使用子类的特有方法,只有子类型可以用,可以向下转型----强制转换。

1 Animal a = new Dog();
2 a.eat();
3 Dog d = (Dog)a;//将a转型到Dog类型---向下转型
4 d.lookhome();

注意:向上向下转型,最终都是子类对象做类型的变化。但是容易引发ClassCastException异常。所以再需要向下转型前,需要做类型的判断。关键字instanceof

1 if(a instanceof Cat)//a指向的对象的类型是cat类型
2 {
3     //将a转型为Cat类型‘
4     Cat c = (Cat)a;
5     c.catchMouse();
6 }

 6.3 多态---成员变量的特点

  • 成员变量

          当子父类中出现同名的成员变量时,多态调用该变量时,

          编译时期,参考的是引用型变量所属的类中是否有被调用的成员变量,没有则编译失败。

     运行时期,也是引用型变量所属的类中是否有被调用的成员变量。【总】编译和运行都参考等号左边

 1 class Fu
 2 {
 3     int num = 3;
 4 }
 5 class Zi extends Fu
 6 {
 7     int num = 5;
 8 }
 9 class Demo3
10 {
11     public static void main(String[] args)
12     {
13         Fu f = new Zi();
14         System.out.println(f.num); 结果是3
15         Zi z = new Zi();
16         System.out.println(z.num);  结果是5 
17     }
18 }
  • 成员函数【动态绑定到对象上】

   编译:参考左边,如果没有,编译失败;

      运行:参考右边的对象所属的类,编译看左边,运行看右边

 1 class Fu
 2 {
 3     void show()
 4     {
 5         System.out.println("fu show");
 6     }
 7 }
 8 class Zi extends Fu
 9 {
10     void show()
11     {
12         System.out.println("zi show");
13     }
14 }
15 class Demo3
16 {
17     public static void main(String[] args)
18     {
19         Fu f = new Zi();
20         System.out.println(f.show());//结果是 zi show
21     }
22 }
  •  静态函数【静态绑定到类上】

         编译运行都遵从左边。真正开发静态方法是不会被多态调用的。因为静态不是所属于对象,而动态是根据对象而言的。静态所属类。

class Fu
{
    static void method()
    {
        System.out.println("fu static method");
    }
}
class Zi extends Fu
{
    static void method()
    {
        System.out.println("zi static method");
    }
}
class Demo3
{
    public static void main(String[] args)
    {
        Fu f = new Zi();
        System.out.println(f.method());//输出结果是 fu static method
} }

 6.4 面向对象--Object

Object类中的常用方法:Object类是所有类的根类,定义了所有对象都具备的功能。

Java中的区:本地区,栈区,代码区,静态区,堆区;

1
2
3
4
5
6
7
8
9
10
 
class ObjectDemo 
{
    
public static void main(String[] args) 
    {
        Person p1 = 
new Person(12);
        System.out.println(p1.toString());
        
//toString()返回一个字符串,最好覆盖重写toString()
    }
}

 6.5 面向对象---内部类

当A类中的内容要被B类直接访问,而A类还需要创建B的对象,访问B的内容时,

这时,可以将B类定义到A类的内部。这样访问更为便捷;

将B称之为内部类(内置类,嵌套类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
class Outer  外部类
{
    
private int num = 4;
    public  
class Inner  内部类  //public一般不用再内部类,因为内部类已经封装到外部类中,不直接对外提供。
    {
        
void show()
        {
            System.out.println(
"num"+num);
        }
//非静态内部类中不允许定义静态成员,仅允许在非静态内部类中定义,静态常量static final
//如果想在内部类中定义静态成员,必须内部类也要被静态修饰。

    }
    
static class Inter2 //内部类被静态修时候,随着outer的加载而加载。可以认为静态内部类是一个外部类
{
    void show2()
    {
        System.out.println("Inner2 show2 run");
    }
   static void staticShow()
   {
      System.out.println("Inner2 staticShow run");
   }
}
    void method()
    {
         Inner h = 
new Inner();
    Outer.Inter in = new Outer.Inner(); //这是内部类的全名
        h.show();
    }
}

 访问方式:内部类可以直接访问外部类中的所有成员,包括私有成员,而外部类要想访问内部类中的成员,必须创建内部类对象。

 直接访问outer中的Inner内部类的非静态成员----直接创建内部类的对象,内部类作为对象为成员,应该先有个外部类对象,再有个内部类。 Outer.Inner in = new Outer().new Inner(); 

 测试情况2:对静态内部类中的非静态成员进行调用,因为内部类是静态类,所以不需要创建Outer的对象,直接创建内部类对象就好了。

Outer.Inner2 in = new Outer. Inner2(); //j静态调用

 如果静态内部类有静态成员,该如何访问呢?既然静态内部类已随外部类加载,而且静态成员随着类的加载而加载。

就不需要对象,直接用类名调用即可。

Outer.Inner2.staticShow();
  • 为什么内部类就能直接访问外部类中的成员?

       那是因为内部类其实持有了外部类的引用, 即外部类.this。 对于静态内部类不持有外部类.this,而是直接使用外部类名。

class Outer
{
	int num = 3;
	class Inter
	{
		void show()
		{
			System.out.println(Outer.this.num);
			System.out.println(num);
		}
	}
}
  • 内部类其实也可以定义在外部类的局部位置上

      内部类定义在局部时,只能访问final 修饰的局部变量,因为编译生产的class中直接操作那个最终值。但是局部类不能被成员修饰符修饰。

  • 内部类时可以继承或者实现外部其他的类或者接口的
abstract class AbsDemo
{
	abstract void show();
}
class Outer
{
	int num = 3;
	class Inner extends AbsDemo  //内部类继承外部类,且会生成一个Outer$Inner.class文件,供外部调用, 
	 //注意这里的内部类不是private型,因而这个类可以对外提供 
{ //重写抽象方法show,覆盖 void show() { System.out.println("num=" + num); } } public void method() { new Inner().show();//匿名对象 } } class InnerClassDemo { public static void main(String[] args) { Outer out = new Outer(); out.method(); } }
  • 若内部类被私有化之后,则需要通过父类或者接口的方式访问到内部类
abstract class AbsDemo
{
	abstract void show();
}
class Outer
{
	int num = 3;
	private class Inner extends AbsDemo //内部类被封装,外部类都不可以对其访问,但是可以访问其父类
	{
		//重写抽象方法show,覆盖
		void show()
		{
			System.out.println("num=" + num);
		}
	}
	//获取内部类的对象
	public AbsDemo getObject()
	{
		return new Inner();
	}
	
	public void method()
	{
		new Inner().show();//匿名对象
	}
}
class InnerClassDemo
{
	public static void main(String[] args)
	{
		Outer out = new Outer();
		//如果Inner被private,可以通过父类型获取
		Abstract a = Out.getObject();//多态,成员函数返回子类,但是可以赋值给父类
		a.show();
	}
}

6.6 匿名对象

 

abstract class AbsDemo
{
	abstract void show();
}
class Outer
{
	int num = 3;
	
	public void method()
	{
		/*不想创建具体的子类型,还想创建AbsDemo的
		子类对象。怎么实现呢?没有子类型干脆,直
		接使用父类型。但是父类是抽象类,如何可以new对象呢?
		抽象类之所以不能创建对象,就是因为抽象方
		法没有重写。
		*/
		new AbsDemo()
		/*这是一个AbsDemo的子类对象,这是一个带着内容的子类对象。匿名对象类*/
		{
			//重写抽象的show方法
			void show()
			{
				System.out.println("num = "+ num);
			}		
		}.show()
	}
}
class InnerClassDemo
{
	public static void main(String[] args)
	{
		Outer out = new Outer();
		out.method();
	}
}

 在这里,简单的介绍一个内部类的使用。前提是内部类最多只有两个方法。

interface Inter
{
	void show1();
	void show2();
}
class Outer
{
	int num = 4;
	//在一个类使用一个接口的对象,可以通过内部类来实现
	class Inner implements Inter
	{
		public void show1();
		public void show2();
	}
	//优化内部类使用接口对象,用匿名内部类来实现
	Inter in = new Inter()
	{
		public void show1(){}
		public void show2(){}
	};
	in.show1();
	in.show2();
}

7 异常处理

7.1 异常处理的简要知识点

异常:

1、JAVA运行时发生的问题就是异常。

2、Java运行时发生的除了异常Exception还有错误Erro;

 异常与错误的区别: 

异常:通常发生可以有针对性的 处理方式的;

错误:通常发生后不会有针对性的处理方式的。Error的发生往往都是系统级别的问题,都是JVM所在系统发生的并反馈给JVM的。无法针对性处理。只能修改代码。

  throw和throws的区别 

1、throw用在函数内;
throw用在函数上;
2、throw抛出的是异常对象;
throws用于进行异常类的声明,后面异常类可以有多个,用逗号隔开

 举个例子、 

class NoShowException extends Exception
{
	NoShowException(String message)
	{
		super(message);
	}
}

class Demo
{
	void show(int num)throws NoShowException
	{
		if(num < 0)
		{
			throw new NoShowException(num+",数值是违法的");	
		}
		System.out.println("show...."+num);
	}
}
class ExceptionDemo9
{
   public static void main(String[] args)
   {
		Demo d = new Demo();
		/*
		因为调用到了声明异常的show方法,所以
		调用者要给处理方式,要么继续声明,
		要么捕获异常
		*/
		try
		{
			d.show();
			System.out.println("hello");
		}
		catch (NoShowException ex)
		{
			System.out.println(ex.toString());
		}
   }
}

7.2 异常---finally的使用

/*
需求:有一些特定的代码无论异常是否发生,
都需要执行,因为异常会引发程序跳转,导致
有写语句执行不到。无法满足这个需求。异常捕获
处理 时java提供了解决方案。就是finally。这个代
码块中存放的代码都是一定会被执行的
*/

 特殊情况: 只有一种情况,finally不执行,就是System.exit(0);

class ExceptionDemo9
{
   public static void main(String[] args)
   {
		Demo d = new Demo();
		/*
		因为调用到了声明异常的show方法,所以
		调用者要给处理方式,要么继续声明,
		要么捕获异常
		*/
		try
		{
			d.show();
			
		}
		catch (NoShowException ex)
		{
			System.out.println(ex.toString());
			//如果发生异常,处理完毕,功能结束
			return;
		}
          
        System.out.println("hello");//异常发生之后,因为有return语句,所以此语句不会执行,
		finally
	      {
			System.out.println("hello");//异常即使发生,也会执行该语句
	      }
   }
}

 总结:finally用处: 

只要程序中使用到了具体的资源(数据库连接,IO资源,网络连接socket等)需要释放,都必须定义在finally中。你在定义程序,只要问题发生与否,指定程序都需要执行时,就定义finally中。

定义一个功能往数据中添加数据
void add (Data data)throws NoAddException
{
	/*1、连接数据库;*/
	try{
	/*2、添加数据
	   添加数据时发生异常情况,throw new 
	   SQLException();程序跳转,就执行不
	   到断开连接。无论是否发生问题,都
	   需要执行断开连接的动作,从而释放资源*/
	}catch(SQLException e)
	{
		/*解决数据库的问题;
	    同时将问题告诉调用者*/
		throw new NoAddException();
	}
	finally
	{
		/*3、断开连接*/
	}
}

 7.3 try catch finally组合方式

 1try catch组合: 

对代码进行异常检测,并对检测的异常传递给catch处理,异常捕获处理。

void show()//此时此处不需要throws
{ 
    try
    {
	throw new Exception();
    }
    catch(Exception e)
    {
	//若此处有一个throw e;语句,则throws必须含有,因为有throw要么有catch要么有throws
    }	
}

 2try finally组合: 

对代码进行异常检测,检测到异常后因为没有catch,所以一样会被默认JVM抛出。异常时没有后捕获处理的。但是功能所开启资源需要进行关闭,所有finally,只为关闭资源。

void show()throws
{ 
   try
   {
	throw new Exception();
   }
   finally
   {
   
   }
}

 3try catch finally组合: 

检测异常并传递给catch处理,并定义资源释放;

try
{}
catch
{}
finally
{}

  异常在继承或者实现中的使用细节:★★★★★ 

  1. 子类覆盖父类方法时,如果父类的方法声明异常,子类只能声明父类异常或者该异常的子类,或者不声明。
  2. 当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集。也可以声明单个父类异常
  3. 当被覆盖的方法没有异常声明时,子类覆盖时时无法声明异常的。举例如下
1 举例:父类存在这种情况,接口也有这种情况,
2     问题:接口中没有声明异常,而实现的子类覆盖方法时发生了异常,怎么办?
3     解决方法:无法进行throws声明,只能catch的捕获。万一问题处理不了呢?catch中继续throw抛出,但是只能将异常转换成RuntimeException子类抛出。
View Code
Interface Inter
{
	public void show();
}
class Demo implement Inter
{
	public void show() //这里不能声明异常throws
	{
	try{
		throw new Exception();
		}catch(Exception e)
		{
			code...;
			throw new RuntimeException("");// 告知调用者问题所在。
		}	
	}
}

8 包package

8.1 包package的使用

对于多个类为了便于管理(类的同名情况),所以java提供了一个解决方案。
包机制:落实到操作系统上,就是文件夹。对Java的文件进行分文件夹管理。

例如: package mypack; //包名中的所有的字母都小写。

 包的作用 

  • 对类文件进行管理。
  • 给类文件提供了名称空间。

 包的定义: 使用关键字 package。

 包的生成: 对带有package定义的java文件进行指定类文件位置的编译方式。javac -d 目录 源文件。

例如:javac -d D:\class xxx.java 则会在D:class目录下生成文件夹 mypack,然后文件夹下生成xxx.class。

8.2 包与包之间的访问

 DemoA.java 

package packa;
public class DemoA //为了使其他包内的类对其进行访问,则需要提高访问权限,即添加public 
{
	public void show()//因为要被其他包内的类进行访问,因而必须提高权限,即添加public
	{
		System.out.println("demoa show run");
	}
}

 PackageDemo.java 要访问包pack中的类,而这个包在D:class目录下,则需要先 set classpath=包所在的父目录 

class PackageDemo 
{
	public static void main(String[] args) 
	{
		packa.DemoA d = new packa.DemoA();//访问DemoA.java中的类
		DemoA d = new DemoA();
		d.show();
	}
}

 总结: 
包与包之间的类在访问时,被访问的类以及成员都必须public修饰。

注意:被public修饰的类或者接口,所属的java文件名必须和类或者接口名称一致。

8.3 包之间的继承关系

包与包之间继承。父类可以给其他包中的子类提供一个特殊的权限 protected。只有继承为子类后,
就可以访问的权限

  public protected default private
一个类中 ok ok ok ok
一个包中 ok ok ok  
子类中 ok ok    
不同包中 ok      

包与包之间访问只有两种权限可以用,public protected(该权限只能给不同包中的子类使用)。

包的出现,导致类的名称过长书写不方便,咋办?
可以通过指定的关键字解决:import :导入。
import作用简化类名书写,省略包名。

特殊情况一: packa\packaa\DemoAA.class\DemoA.class 

import packa.*;//明确类使用的类所属的包是packa。不会导入packa中子包中的类。
如果要使用DemoAA。
import packa.packaa.*;
new DemoAA();
特殊情况二:不同包中有了相同名称的类。使用该类时必须指定包名。

packa\Demo.class
packb\Demo.class

import packa.Demo;
import packb.Demo;

new packa.Demo();

在命令行中,添加 jar包 
 jar -cvf haha.jar pack //就是将pack包压缩到hahha.jar归档文件中。
使用方法:
就是对jar进行设置path。
 set classpath =.\haha.jar 

posted @ 2018-08-16 23:11  繁星的夜空2012  阅读(171)  评论(0编辑  收藏  举报