======================================================================
Java 第 6 天 : Java 高级特性
修饰符 ; 接口 , 内部类 , 对象 , 包装类 , 集合 , 异常处理 , 反射 .
======================================================================
(1) 修饰符。
private,default,protected,public // 不能修饰局部变量
private,default,protected,public: 都能修饰属性和方法 ,
但是只有 default,public 能修饰类 .
Java 第 6 天 : Java 高级特性
修饰符 ; 接口 , 内部类 , 对象 , 包装类 , 集合 , 异常处理 , 反射 .
======================================================================
(1) 修饰符。
private,default,protected,public // 不能修饰局部变量
private,default,protected,public: 都能修饰属性和方法 ,
但是只有 default,public 能修饰类 .
表1:
类,方法,成员变量和局部变量的可用修饰符
修饰符
|
类
|
成员方法
|
构造方法
|
成员变量
|
局部变量
|
abstract
|
√
|
√
|
-
|
-
|
-
|
static
|
-
|
√
|
-
|
√
|
-
|
public
|
√
|
√
|
√
|
√
|
-
|
protected
|
-
|
√
|
√
|
√
|
-
|
private
|
-
|
√
|
√
|
-
|
-
|
synchronized
|
-
|
√
|
-
|
-
|
-
|
native
|
-
|
√
|
-
|
-
|
-
|
transient(
暂时的
)
|
-
|
-
|
-
|
√
|
-
|
volatile(
易失的
)
|
-
|
-
|
-
|
√
|
-
|
final
|
√
|
√
|
-
|
√
|
√
|
表
2 :
访问的级别和可访问范围
访问级别
|
访问控制修饰参数
|
同类
|
同包
|
子类
|
不同的包
|
公开
|
Public
|
√
|
√
|
√
|
√
|
受保护
|
Protected
|
√
|
√
|
√
|
-
|
默认
|
Default(
没有修饰
)
|
√
|
√
|
-
|
-
|
私有
|
private
|
√
|
-
|
-
|
-
|
(2) static // 静态的 .
能修饰属性 , 方法 , 初始代码块 .
package test;
public
class
TestStatic {
public
static
void
main(String[] args){
MyClass mc1=
new
MyClass();
MyClass mc2=
new
MyClass();
mc1.
a
=10;
System.
out
.print(
"mc1.a="
+mc1.
a
);
System.
out
.print(
"mc2.a="
+mc2.
a
);
mc2.
a
=20;
System.
out
.print(
"mc1.a="
+mc1.
a
);
System.
out
.print(
"mc2.a="
+mc2.
a
);
System.
out
.print(
"MyClass.a="
+MyClass.
a
);
//
因为
a
是类变量
,
所以可以用类名调用
.
System.
out
.println();
// out
是
System
里的公有的属性
.
MyClass.m1();
//
类名调用
.
}
}
class
MyClass{
static
int
a
=1;
//
此时叫类变量
,
全类公有
.
因此可以用类名调用
.
int
b
=2;
//
创建对象的时候才分配空间
,
初始化
.
public
static
void
m1(){
System.
out
.println(
a
);
System.
out
.println(
b
);
//
静态方法不能访问非静态属性。
}
public
static
void
m2(){
//
相当于全类的
,
因此能用类名调用
.
是打破面向对象思想的
.
System.
out
.println(
a
);
System.
out
.println(
b
);
//
编译错误
,
静态方法不能访问非静态属性
.
因为
,
}
}
属性
:
类变量
(static),
实例变量
.
局部变量不是属性 .
(4) 静态方法是否能覆盖 ?
静态方法可以覆盖 , 但是必需是静态方法覆盖静态方法 , 非静态方法不能覆盖静态方法 .( 此时就没有了多态 .)
package test;
局部变量不是属性 .
(4) 静态方法是否能覆盖 ?
静态方法可以覆盖 , 但是必需是静态方法覆盖静态方法 , 非静态方法不能覆盖静态方法 .( 此时就没有了多态 .)
package test;
class
TestOverride{
public
static
void
main(String[] args){
Super s=
new
Sub();
//
只有非静态方法的覆盖才有多态
.
System.
out
.println(s.
a
);
// =10
}
}
class
Super{
static
int
a
=10;
}
class
Sub
extends
Super{
static
int
a
=20;
}
(5) 静态属性是在什么时候 , 被初始化的 ???
答 : 在类加载的时候被初始化的 .
(7) 什么叫类加载 ??
答 : 类加载一次 , 然后就创建静态变量 .( 也就是只创建一次 ). 如果创建对象就不用再次的加载类 , 在然后就创建对象 . 一个类在编译之后会形成 .class 文件 , 存储了类的全部消息 . 当 JVM 第一次需要用到这个类的时候 , 会根据 ClassPath 找到这个 .class 文件 , 用输入流把文件中的消息读入 JVM 并保存起来 , 这样 ,JVM 就 " 认识 " 了这个类 .
类加载时机 : 第一次用这个类的时候 .
1. 第一次创建类的对象 , 会加载
2. 访问类的静态成员 , 会加载 .
3. 声明类的引用 , 不会加载 .
4. 加载子类 , 必然先加载父类
5. 如果调用的是子类从父类中继承到静态方法 , 只会加载父类 .
6. 如果访问的是类的静态常量 , 如果在编译的时候能确定这个常量的值 , 则运行时不会加载 , 否则 , 编译是无法确定常量的值 , 那么运行是就会加载 .
(8) 主方法为什么是静态方法 ?
答 : 如果不是静态的 . 必需先创建类对象 , 但是此时创建对象的方法是 main 方法里面 , 这样会造成矛盾 . 也就是不能创建对象 . 要解决这个问题就要把 main 方法写成静态的 , 要让 main 方法在创建对象之前调用 ( 因为静态方法和属性是在类加载的时候就调用的 , 因此可以解决这个问题 , 呵呵 )
(9)static 的第三种用法 .( 温馨提示 :static 的前三种用法是 :1. 修饰属性 ,2. 方法 ,3. 初始化代码块 )
// 此时而初始化代码块只能用 static 修饰 , 嘻嘻记住吧 !!!
在第三步 : 调用初始代码块 : 在构造方法前面运行,在初始化属性的时候运行。
在前面加 static 静态初始代码快 . 在类加载的时候运行 , 创建对象的时候不运行这个代码块 .// 太有用了 !! 呵呵 .
重要用处 : 监控虚拟机的类加载 .
1. 创建对象的时候会出现 .
2. 第一次访问静态方法 , 属性 .
3. 声明一个类的一个引用 , 不会加载类 . 虚拟机有延迟加载的功能 ,( 能不加载就不加载 , 也就是编译器能确定的事情 [ 也就是不变的量 ,final 修饰 ], 就不会加载类 , 这样会浪费内存 )
4. 加载子类的时候会加载父类么 ????
答 : 不单要加载父类而且会先加载父类 .
例子 : 看老师的代码 : TestClassLoad.java
5. 如果你调用从父类继承到的静态方法 , 只加载父类不加载子类 .
例子 : 例子 : 看老师的代码 : TestClassLoad.java
如果覆盖了父类的静态方法 , 就还要加载子类 .
这 5 个特性都在下面的代码中 :
package test;
(5) 静态属性是在什么时候 , 被初始化的 ???
答 : 在类加载的时候被初始化的 .
(7) 什么叫类加载 ??
答 : 类加载一次 , 然后就创建静态变量 .( 也就是只创建一次 ). 如果创建对象就不用再次的加载类 , 在然后就创建对象 . 一个类在编译之后会形成 .class 文件 , 存储了类的全部消息 . 当 JVM 第一次需要用到这个类的时候 , 会根据 ClassPath 找到这个 .class 文件 , 用输入流把文件中的消息读入 JVM 并保存起来 , 这样 ,JVM 就 " 认识 " 了这个类 .
类加载时机 : 第一次用这个类的时候 .
1. 第一次创建类的对象 , 会加载
2. 访问类的静态成员 , 会加载 .
3. 声明类的引用 , 不会加载 .
4. 加载子类 , 必然先加载父类
5. 如果调用的是子类从父类中继承到静态方法 , 只会加载父类 .
6. 如果访问的是类的静态常量 , 如果在编译的时候能确定这个常量的值 , 则运行时不会加载 , 否则 , 编译是无法确定常量的值 , 那么运行是就会加载 .
(8) 主方法为什么是静态方法 ?
答 : 如果不是静态的 . 必需先创建类对象 , 但是此时创建对象的方法是 main 方法里面 , 这样会造成矛盾 . 也就是不能创建对象 . 要解决这个问题就要把 main 方法写成静态的 , 要让 main 方法在创建对象之前调用 ( 因为静态方法和属性是在类加载的时候就调用的 , 因此可以解决这个问题 , 呵呵 )
(9)static 的第三种用法 .( 温馨提示 :static 的前三种用法是 :1. 修饰属性 ,2. 方法 ,3. 初始化代码块 )
// 此时而初始化代码块只能用 static 修饰 , 嘻嘻记住吧 !!!
在第三步 : 调用初始代码块 : 在构造方法前面运行,在初始化属性的时候运行。
在前面加 static 静态初始代码快 . 在类加载的时候运行 , 创建对象的时候不运行这个代码块 .// 太有用了 !! 呵呵 .
重要用处 : 监控虚拟机的类加载 .
1. 创建对象的时候会出现 .
2. 第一次访问静态方法 , 属性 .
3. 声明一个类的一个引用 , 不会加载类 . 虚拟机有延迟加载的功能 ,( 能不加载就不加载 , 也就是编译器能确定的事情 [ 也就是不变的量 ,final 修饰 ], 就不会加载类 , 这样会浪费内存 )
4. 加载子类的时候会加载父类么 ????
答 : 不单要加载父类而且会先加载父类 .
例子 : 看老师的代码 : TestClassLoad.java
5. 如果你调用从父类继承到的静态方法 , 只加载父类不加载子类 .
例子 : 例子 : 看老师的代码 : TestClassLoad.java
如果覆盖了父类的静态方法 , 就还要加载子类 .
这 5 个特性都在下面的代码中 :
package test;
public
class
TestClassLoad{
public
static
void
main(String[] args){
// Student s=new Student();
// Student.m();
// Student s=null;
// Sub s=new Sub();
// Sub.m();
// System.out.println(ClassA.A);//
这个就不会调入虚拟机
.(
编译器当时就确定了这个数
,
因此就没有必要加载这个类
,
会省下内存空间
,
呵呵
)
System.
out
.println(ClassA.
B
);
//
此时会加载类
.
因为
Math.random();
的值不确定
,
要进入类才能知道
.
}
}
class
Student{
static
{
//
修饰的初始化代码块
.[
温馨提示
:
此时只能用
static
修饰
,
不能用
private,protect,public
修饰
,
嘻嘻
]
System.
out
.println(
"Load Student"
);
}
static
int
a
;
public
static
void
m(){}
public
Student(){}
}
class
Super{
//
验证
[
加载子类的时候会加载父类么
]
static
{
System.
out
.println(
"Load Super"
);
}
public
static
void
m(){}
}
class
Sub
extends
Super{
static
{
System.
out
.println(
"Load Sub"
);
}
}
class
ClassA{
//
验证编译器确定了变量的值
,
就不会加载类
static
{
System.
out
.println(
"Load ClassA"
);
}
public
static
final
int
A
=2*5;
//
确定不会变的量
.
public
static
final
double
B
=Math.random();
//
只有调入这个类才能确定的量
.
}
(10) 和静态有关的模式模式: GOF green of four; 23种模式
1.单例模式: (yi) 一个类只允许他有一个对象.怎么实现??
就要用到单例模式.
具体例子: 这样一个类才只能有一个对象. 实现了这个需求.呵呵.
package test;
(10) 和静态有关的模式模式: GOF green of four; 23种模式
1.单例模式: (yi) 一个类只允许他有一个对象.怎么实现??
就要用到单例模式.
具体例子: 这样一个类才只能有一个对象. 实现了这个需求.呵呵.
package test;
public
class
TestClassLoad{
public
static
void
main(String[] args){
LaoGong lg1=LaoGong.newInstance();
LaoGong lg2=LaoGong.newInstance();
LaoGong lg3=
new
LaoGong();
//
这个会出现编译错误
,
把无参的构造方法变成私有。
LaoGong lg4=LaoGong.newInstance();
//
只有这样才能编译通过
.
System.
out
.println(
""
);
}
}
class
LaoGong{
private
static
LaoGong
lg
=
new
LaoGong();
//
单例模式
;
public
static
LaoGong newInstance(){
//
返回申请的同一个对象。
lg;
return
lg
;
}
private
LaoGong(){}
//
把
LaoGong lg=new LaoGong()
路给堵上
.
}
虚拟机机制: 一般来说一个类只加载一次.
java 起动一个虚拟机.
(11) 如果设计一个方法, 不需要对象. 就用static 修饰. 一般用于JDK 的工具类的。
(12) final 修饰变量.3 个变量都能修饰 , 还能修饰类.
//对于类常量,初始化或者静态初始化代码块中可以赋值.
虚拟机机制: 一般来说一个类只加载一次.
java 起动一个虚拟机.
(11) 如果设计一个方法, 不需要对象. 就用static 修饰. 一般用于JDK 的工具类的。
(12) final 修饰变量.3 个变量都能修饰 , 还能修饰类.
//对于类常量,初始化或者静态初始化代码块中可以赋值.
1. final 修饰变量
这个变量就变成了常量(一旦赋值,以后就不能改变了)//和conste一样,来定义常量.final修饰的变量有两次赋值的机会:申请变量的时候,在构造函数中。
package test;
package test;
public
class
TestFinal {
public
static
void
main(String[] args) {
ClassA cs =
new
ClassA();
System.
out
.println(cs.B);
//
这样会编译错误
.
没有初始化
,
因为
final
要进行初始化。
cs.B = 10;
//
无法为最终变量
B
指定值
.
因此要在创建对象时赋值。
.
}
}
class
ClassA {
final
int
B;
//
如果
,
加了
final
默认值无效
.
因为是常量所以要是大写
.
final
int
B = 10;
//
第一种赋值的方法
.
public
ClassA(){}
public
ClassA(
int
b) {
//
第二种赋值方法
.
this
.B = B;
}
public
void
m() {
int
a = 10;
a = 20;
}
}
2. final 修饰类和方法 .
例子: 修饰类,则这个类没有子类,如果一个类用final修饰,那么这个类不能被继承.
final class Super{ // 编译错误 , 无法从最终类继承 . 例子 : String 类是一个 final 类 .
public final void m(){} // 如果一个类用 final 修饰 , 那么这个类不能被继承 .
}
//final 的用处 : 自己写的方法 , 不希望被子类修改 , 保持了方法的稳定性 .
class Sub extends Super{
public void m(){} // 编译错误 . 无法覆盖因为被覆盖的方法是 final.
}
// 判断 : 一个 final 类的其中所有的方法全是 final ????? 对了 , 呵呵 .
public static final double A=3.14//公开静态常量.
======================================================================
package test;
2. final 修饰类和方法 .
例子: 修饰类,则这个类没有子类,如果一个类用final修饰,那么这个类不能被继承.
final class Super{ // 编译错误 , 无法从最终类继承 . 例子 : String 类是一个 final 类 .
public final void m(){} // 如果一个类用 final 修饰 , 那么这个类不能被继承 .
}
//final 的用处 : 自己写的方法 , 不希望被子类修改 , 保持了方法的稳定性 .
class Sub extends Super{
public void m(){} // 编译错误 . 无法覆盖因为被覆盖的方法是 final.
}
// 判断 : 一个 final 类的其中所有的方法全是 final ????? 对了 , 呵呵 .
public static final double A=3.14//公开静态常量.
======================================================================
package test;
public
class
TestFinal {
public
static
void
main(String[] args) {
ClassA cs =
new
ClassA();
System.
out
.println(cs.
A
);
//
编译器在编译的时候
System.out.println(10);10
//
是静态常量
.
因此不会加载
ClassA();
System.
out
.println(cs.
B
);
//
编译器在编译的时候不能确定
B
的值
,
因此会加载
ClassA();
}
}
class
ClassA {
static
{
System.
out
.
println
(
"Load ClassA"
);
}
public
static
final
int
A
= 2 * 5;
//
编译器能确定,因此就不装载子类了。
public
static
final
double
B
= Math.random();
//
编译器不能确定此时的值,因此要装载子类。
}
======================================================================
(14) abstract 表示抽象的 修饰类, 方法,抽象类:用来被继承.
抽象方法:只有定义没有实现.如果一个类里边有抽象方法,这个类必需是抽象类.一个抽象类,并不一定有抽象方法.
抽象类有构造方法
通过abstract,我们可以把一个方法定义
例子:
package test;
======================================================================
(14) abstract 表示抽象的 修饰类, 方法,抽象类:用来被继承.
抽象方法:只有定义没有实现.如果一个类里边有抽象方法,这个类必需是抽象类.一个抽象类,并不一定有抽象方法.
抽象类有构造方法
通过abstract,我们可以把一个方法定义
例子:
package test;
public
class
TestAbstact{
public
static
void
main(String[] args){
Super s=
new
Super();
//
是抽象的不能去创建对象
,
因此不能作为运行时类型
.
Super s;
//
可以声明引用
.
他是用来被继承的
.
Super s=
new
Sub();
//
可以
,
抽象类可以作为一个类的半成品
.(
抽象类作为编译时类型
,
子类作为运行时类型
.)
s.m();
//
找子类中实现的方法
.
}
}
abstract
class
Super{
public
abstract
void
m();
//
抽象方法
,
只有声明没有实现
.
}
class
Sub
extends
Super{
//
如果不实现他
,
就不会编译通过
,
嘻嘻
,
必需全部实现父类的抽象方法
.
public
void
m(){
System.
out
.println(
"hehe"
);
//
实现了父类的这个方法
.
呵呵
.
}
}
final abstract 都不能修饰构造方法.
======================================================
(14) 修饰符的组合方式;final abstract 都不能修饰构造方法.
抽象类,可以有构造方法,是让子类调用的.
但是,接口没有构造方法.
private ,static,final 可以任意的组合,去修饰一个方法.
三个任意一个都不能和abstract 和用在一起.
private
static 不能混用 abstract
final
---------------------------------------------
抽象方法的作用:
======================================================================
(15) 接口语法:
1. 一个接口就是一个抽象类,而且是一个特殊的抽象类,所有属性默认都是公开静态常量,所有的方法默认都是公开抽象方法.接口之间可以多继承.一个类在继承另外一个类的同时,还可以实现多个接口,
2. 一个类实现一个接口,如果这个类不是抽象类的化,那么就一定要实现接口中定义的方法.
3. 接口没有构造方法.
例子:
package test;
final abstract 都不能修饰构造方法.
======================================================
(14) 修饰符的组合方式;final abstract 都不能修饰构造方法.
抽象类,可以有构造方法,是让子类调用的.
但是,接口没有构造方法.
private ,static,final 可以任意的组合,去修饰一个方法.
三个任意一个都不能和abstract 和用在一起.
private
static 不能混用 abstract
final
---------------------------------------------
抽象方法的作用:
======================================================================
(15) 接口语法:
1. 一个接口就是一个抽象类,而且是一个特殊的抽象类,所有属性默认都是公开静态常量,所有的方法默认都是公开抽象方法.接口之间可以多继承.一个类在继承另外一个类的同时,还可以实现多个接口,
2. 一个类实现一个接口,如果这个类不是抽象类的化,那么就一定要实现接口中定义的方法.
3. 接口没有构造方法.
例子:
package test;
public
class
TestInterface{
public
static
void
main(String[] args){
Impl i=
new
Impl();
MyClass mc=i;
mc.m6();
//
只能调用
m6();
IA ia=i;ia.m1();ia.m2();
IB ib=i;ib.m3();
IC ic=i;ic.m1();ic.m2();ic.m3();ic.m4();
ID id=i;is.m5();
}
}
abstract
class
AbstractClass
{
//
接口是特殊的抽象类
public
abstract
void
m1();
}
class
Sub
extends
Super{
public
static
final
int
A
=10;
public
abstract
void
m1();
public
abstract
void
m2();
}
interface
IA{
//
此接口和上一个抽象类在逻辑上是完全等价的
.
int
a
=10;
//
接口的属性
.
接口中属性公开静态常量
.
//
接口中没有构造方法
.
void
m1();
//
接口中所有的方法都是公开抽象方法
.
void
m2();
}
interface
IB{
//
void
m3();
}
interface
IC
extends
IA,IB{
//
接口能够继承
.
而且能够多继承
.
void
m4();
}
interface
ID{
//
void
m5();
//
}
class
Impl
extends
IA{
//
错误
,
类和类之间有继承
,
接口和接口之间有继承
,
类和接口之间只有实现
.
}
class
Impl
implements
IA{
//
实现接口也要实现里面的抽象方法
.
void
m1(){}
//
编译不通过
public
void
m1(){}
//
这样才能编译通过
,
嘻嘻
.
public
void
m2(){}
//
这样才能编译通过
,
嘻嘻
.
}
abstract
class
MyClass{
public
void
m6() {
}
}
class
Impl
extends
MyClass
implements
IC,ID{
//
这样会绕过单继承的限制
,
而且可以继承多个接口
.
public
void
m1(){}
public
void
m2(){}
public
void
m3(){}
public
void
m4(){}
public
void
m5(){}
public
void
m6(){}
}
class
Sub
extends
Super{
public
abstract
void
m1();
public
abstract
void
m2();
}
class
Super{
}
======================================================================
以下是老师的笔记:
以下是老师的笔记:
static
属性 类变量 全类共有 类加载时创建,类名访问
方法 类名调用,静态方法中不能访问类的非静态成员,可以覆盖,只能被静态方法覆盖,没有多态
初始代码块 类加载时运行
类加载:
一个类编译之后会形成.class文件,储存了类的全部信息。当JVM第一次需要用到这个类的时候,会根据ClassPath找到这个.class文件,用输入流把文件中的信息读入JVM并保存起来,这样,JVM就“认识”了这个类
类加载时机:第一次用这个类的时候
1. 第一次创建类的对象,会加载
2. 访问类的静态成员,会加载
3. 声明类的引用,不会加载
4. 加载子类,必然先加载父类
5. 如果调用的是子类从父类中继承到的静态方法,只会加载父类
6. 如果访问的是类的静态常量,如果在编译的时候能够确定这个常量的值,则运行时不会加载,否则,编译时无法确定常量值,那么运行时就会加载
设计模式:单例模式
用途:一个类只能有一个对象
实现:会有一个静态的属性,就是该类的一个对象。提供一个静态方法,来获得这个唯一的静态属性(单例),同时构造方法私有
final
变量:常量,一旦赋值,不能改变,为属性常量赋值的时机:对于实例常量,初始化或者构造方法中可以赋值;对于类常量,初始化或者静态初始代码块中可以赋值
方法:不能被覆盖
类 :不能被继承
abstract
方法:只有定义,没有实现
类:不能构造对象,但可以用来声明一个引用(作为编译时类型)
如果一个类有抽象方法,这个类必须是抽象类,如果一个类是抽象类,不一定有抽象方法
子类继承一个抽象类,就必须覆盖(实现)父类(抽象类)中的所有抽象方法,否则,子类就也得是抽象类
抽象类有构造方法
通过abstract,我们可以把一个方法的定义放在父类,而留给子类实现。
接口
一个接口是一个特殊的抽象类。所有的属性默认都是公开静态常量,所有的方法默认都是公开抽象方法
接口之间可以多继承
一个类在继承另外一个类的同时,还可以实现多个接口。而实现的每一个接口都将成为这个类的兼容类型,允许多态的使用
一个类实现一个接口,如果这个类不是抽象类的话,那么就一定要实现接口中定义的所有方法
接口没有构造方法
接口的作用:
1.实现多继承
区分主类型和次要类型,接口的引入就使得我们可以对事物的共性作一个再抽象,抽象出副类型。
这种多继承的关系不会破坏类之间单继承树状关系的复杂度
2.标准
标准的制定者、实现者、使用者分离
解耦合的工具
标准的使用者和标准的实现者通过接口实现弱耦合
属性 类变量 全类共有 类加载时创建,类名访问
方法 类名调用,静态方法中不能访问类的非静态成员,可以覆盖,只能被静态方法覆盖,没有多态
初始代码块 类加载时运行
类加载:
一个类编译之后会形成.class文件,储存了类的全部信息。当JVM第一次需要用到这个类的时候,会根据ClassPath找到这个.class文件,用输入流把文件中的信息读入JVM并保存起来,这样,JVM就“认识”了这个类
类加载时机:第一次用这个类的时候
1. 第一次创建类的对象,会加载
2. 访问类的静态成员,会加载
3. 声明类的引用,不会加载
4. 加载子类,必然先加载父类
5. 如果调用的是子类从父类中继承到的静态方法,只会加载父类
6. 如果访问的是类的静态常量,如果在编译的时候能够确定这个常量的值,则运行时不会加载,否则,编译时无法确定常量值,那么运行时就会加载
设计模式:单例模式
用途:一个类只能有一个对象
实现:会有一个静态的属性,就是该类的一个对象。提供一个静态方法,来获得这个唯一的静态属性(单例),同时构造方法私有
final
变量:常量,一旦赋值,不能改变,为属性常量赋值的时机:对于实例常量,初始化或者构造方法中可以赋值;对于类常量,初始化或者静态初始代码块中可以赋值
方法:不能被覆盖
类 :不能被继承
abstract
方法:只有定义,没有实现
类:不能构造对象,但可以用来声明一个引用(作为编译时类型)
如果一个类有抽象方法,这个类必须是抽象类,如果一个类是抽象类,不一定有抽象方法
子类继承一个抽象类,就必须覆盖(实现)父类(抽象类)中的所有抽象方法,否则,子类就也得是抽象类
抽象类有构造方法
通过abstract,我们可以把一个方法的定义放在父类,而留给子类实现。
接口
一个接口是一个特殊的抽象类。所有的属性默认都是公开静态常量,所有的方法默认都是公开抽象方法
接口之间可以多继承
一个类在继承另外一个类的同时,还可以实现多个接口。而实现的每一个接口都将成为这个类的兼容类型,允许多态的使用
一个类实现一个接口,如果这个类不是抽象类的话,那么就一定要实现接口中定义的所有方法
接口没有构造方法
接口的作用:
1.实现多继承
区分主类型和次要类型,接口的引入就使得我们可以对事物的共性作一个再抽象,抽象出副类型。
这种多继承的关系不会破坏类之间单继承树状关系的复杂度
2.标准
标准的制定者、实现者、使用者分离
解耦合的工具
标准的使用者和标准的实现者通过接口实现弱耦合