1.接口
接口(interface)是抽象方法和常量值定义的集合。
接口是实现功能,比如,鼠标、键盘、打印机他们都有usb口,这是他们共同的功能,三者之间并不存在子父类的关系
接口的特点:
用
interface
来定义。
接口中的所有成员变量都
默认
是由
public static final
修饰的。
接口中的所有抽象方法都
默认
是由
public abstract
修饰的。
接口中没有构造器。
接口采用多继承机制。
![](https://i-blog.csdnimg.cn/blog_migrate/d0f034d431baaaedf82eea36041ecb50.png)
Java 8
中,你可以为接口添加
静态方法
和
默认方法
。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。
静态方法:
使用
static
关键字修饰。
可以通过接口直接调用静态方法
,并执行其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中找到像Collection/Collections
或者
Path/Paths
这样成对的接口和类。
默认方法:
默认方法使用
default
关键字修饰。可以通过实现类对象来调用。 我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。 比如:java 8 API
中对
Collection
、
List
、
Comparator
等接口提供了丰富的默认方法。
接口中的默认方法
若一个接口中定义了一个默认方法,而另外一个接口中也定义了一个同名同参数的方法(不管此方法是否是默认方法),在实现类同时实现了这两个接口时,会出现:
接口冲突。
解决办法:实现类必须覆盖接口中同名同参数的方法,来解决冲突。
若一个接口中定义了一个默认方法,而父类中也定义了一个同名同参数的非抽象方法,则不会出现冲突问题。因为此时遵守:
类优先原则。
接口中具有相同名称和参数的默认方法会被忽略。
2.代理模式设计模式
代理设计就是为真实对象提供一种代理以控制对这个对象的访问。
实现步骤:
1.接口,
包含要实现的抽象方法
2.被代理类:
重写接口的抽象方法
,实现真实方法的功能
3.代理类:
首先有一个接口的成员变量,然后构造器参数是接口类型的(方便将被代理类传进去),最后重写接口方法
,实现被代理类的真实方法
应用场景:
安全代理:
屏蔽对真实角色的直接访问。
远程代理:
通过代理类处理远程方法调用(
RMI
)
延迟加载:
先加载轻量级的代理对象,真正需要再加载真实对象
比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有
100MB
,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理
模式,当需要查看图片时,用
proxy
来进行大图片的打开。
分类
静态代理
(静态定义代理类)
动态代理
(动态生成代理类)
JDK
自带的动态代理,需要反射等知识
interface A {
int x = 0;
}
class B {
int x = 1;
}
class C extends B implements A {
public void pX() {
System.out.println(x);
}
public static void main(String[] args) {
new C().pX();
} }
有问题,编译不通过。
因为x是不明确的,此时父类和接口对于子类来说是同一条线上的。
开发中尽量不要让属性重名。我们在定义属性的时候尽可能的将名字区分开,不要定义重名的
//正确写法
interface A{
int x=0;
}
class B{
int x=1;
}
class C extends B implements A{
public void pX() {
System.out.orintln(super.x);//调用父类的x
//利用接口中的x是全局常量
System.out.println(A.x);//调用接口中的x
}
public static void main(String[] args) {
new C().pX();
}
}
3.内部类
分类:
成员内部类
(
static
成员内部类和非
static
成员内部类)
局部内部类
(不谈修饰符)
匿名内部类
1.成员内部类
成员内部类作为类的成员的角色:
和外部类不同,
Inner class
还可以声明为
private
或
protected
;
可以调用外部类的结构
Inner class
可以声明为
static
的,但此时就不能再使用外层类的非
static
的成员变量;
成员内部类作为类的角色:
可以在内部定义属性、方法、构造器等结构
可以声明为
abstract
类 ,因此可以被其它的内部类继承
可以声明为
final
的
编译以后生成
OuterClass$InnerClass.class
字节码文件(也适用于局部内部类)
【注意】
1.
非
static
的成员内部类中的成员不能声明为
static
的,只有在外部类或
static
的成员内部类中才可声明static
成员。
2.
外部类访问成员内部类的成员,需要
“
内部类
.
成员
”
或
“
内部类对象
.
成员
”
的方式
3. 成员内部类可以直接使用外部类的所有成员,包括私有的数据
4. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类
声明为静态的
class Outer {
private int s;//成员变量
public class Inner {//内部类
public void mb() {//内部类的方法
s = 100;
System.out.println("在内部类Inner中s=" + s);
}
}
public void ma() {//外部类的方法
Inner i = new Inner();//创建一个内部类对象
i.mb();//调用内部类的方法
}
}
public class InnerTest {
public static void main(String args[]) {
Outer o = new Outer();//创建一个外部类对象
o.ma();//调用外部类的方法
}
}
2.局部内部类
如何使用局部内部类
只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方都不能使用该类
但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类 的父类或父接口类型
局部内部类可以使用外部方法的局部变量,但是必须是
final
的。
由局部内部类和局部变量的声明周期不同所致。
局部内部类和局部变量地位类似,不能使用
public,protected,
缺省
,private
局部内部类不能使用
static
修饰,因此也不能包含静态成员
public class Test2 {
public void method(){//方法
class A{//方法中的局部类
int age;//局部类的成员变量
public int getAge(){//局部类的方法
return age;
}
}
}
}
3.匿名内部类
匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new
的后面,用其隐含实现一个接口或实现一个类。
格式:
new
父类构造器(实参列表)
|
实现接口
(){
//匿名内部类的类体部分
}
匿名内部类的特点
匿名内部类必须继承父类或实现接口
匿名内部类只能有一个对象
匿名内部类对象只能使用多态形式引用
interface A{
public abstract void fun1();
}
public class Outer{
public static void main(String[] args) {
new Outer().callInner(new A(){
//接口是不能new但此处比较特殊是子类对象实现接口,只不过没有为对象取名
public void fun1() {
System.out.println(“implement for fun1");
}
});// 两步写成一步了
}
public void callInner(A a) {
a.fun1();
}
}
4.面向对象总结