目录
三、面向对象
10.抽象类
抽象类特点
抽象类的成员特点
abstract不能和哪些关键字共存
11.接口
接口的概述
接口的特点
接口中的成员特点
类与类,类与接口,接口与接口的关系
抽象类和接口的区别
12.package关键字
包的定义
定义包的注意事项
带包的类编译和运行
13.import关键字
注意事项
package,import,class顺序关系
14.修饰符
四种权限修饰符
类,成员常见修饰符
15.内部类
内部类访问特点
成员内部类私有使用
静态成员内部类
局部内部类
局部内部类访问局部变量的问题
匿名内部类
抽象类和抽象方法必须用abstract修饰
抽象类不一定有抽象方法,但有抽象方法一定是抽象类或者接口
抽象类中没有抽象方法的意义:限制该类无法直接进行实例化,强制通过子类实例化
抽象类不能被直接实例化,因为抽象类实例化没有意义,但可以通过多态的方式,通过子类进行实例化
抽象类的子类要么是抽象类,要么重写父类所有抽象方法(因为有抽象方法就一定是抽象类)
abstract class Animal { //抽象方法,没有具体实现的方法(没有方法体) public abstract void eat(); }
成员变量:可以是变量,常量,但不可用abstract修饰(因为抽象变量,常量没有意义)
构造方法:有,用于子类进行父类初始化
成员方法:可以是抽象或非抽象
抽象方法:强制子类重写
非抽象方法:子类继承使用
static 因为类名调用抽象方法没有意义
final abstract强制子类重写,final修饰的方法不能重写
private abstract强制子类重写,private不让子类继承
狭义上就是interface,广义上对外提供的规则都是接口
接口用关键字interface表示,public interface 接口名{}
类实现接口用implements表示,class 类名 implements 接口名 {}
接口不能实例化,通过多态的方式实例化
接口的子类
可以是抽象类 没什么意义,因为抽象类仍然不能实例化
可以是具体类 重写所有抽象方法
成员变量:只能是常量,默认修饰符 public static final
public:接口的实现类都可以使用该成员(这是显然的,接口无法实例化,不public的话该成员还有什么存在的意义?)
static:表示该成员属于类(接口不能创建对象,所以成员变量肯定属于接口,且接口应该是实现类共性的抽取,用static修饰是理所应当的)
另一种理解方法,如果成员变量不是属于接口,实现多个接口出现重名变量,怎么办?显然需要属于接口,这样可以直接使用接口名调用
final:保证接口所定义的常量不能被实现类去修改,实现类(共性的东西,怎么可能让任意实现类随便修改)
构造方法:接口没有构造方法
成员方法:只能是抽象方法,默认修饰符 public abstract,public 是为了让子类重写
类与类:继承,单继承,多层继承
类与接口:实现,多实现,class Demo implements InterA,InterB {}
接口与接口:继承,可以多继承,interface Demo extends InterA,InterB {}
成员区别
抽象类
成员变量 可以是常量,可以是变量
构造方法 有构造方法,用于子类进行父类初始化
成员方法 可以是抽象或者非抽象方法
接口
成员变量 只能是常量 public static final
构造方法 没有
成员方法 只能是抽象方法 public abstract
关系区别
类与类 继承,单继承,多层继承
类与接口 实现,单实现,多实现
接口与接口 继承,单继承,多继承
设计理念区别
抽象类 is 定义的是某些共性功能
接口 like 定义的是某些拓展功能
包的作用:包就是文件夹,将代码文件按功能,模块分类存放
package 包名;
多级包用.分开即可
package语句必须是程序的第一条可执行的代码
package语句在一个java文件中只能有一个
没有package,默认表示无包名
编译:javac编译的时候带上-d即可,会自动生成包(文件夹),javac -d . HelloWorld.java
运行:通过java命令执行java 包名.HellWord(用全类名访问)
不同包下类之间的访问(封装的一种体现)
用全类名访问(带包的),被访问的应该用public修饰
作用:让有包的类对调用者可见,不再需要写全类名
格式:import 包名;
这种方式导入是到类的名称
虽然可以最后写*,但是不建议,浪费,影响效率(是一种匹配的机制)
package必须第一行可执行语句,仅一句
import放在中间,可以多句
class在最后
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
本类 |
同包(子类和无关类) |
不同包(子类) |
不同包(无关类) |
|
private |
Y |
|||
默认 |
Y |
Y |
||
protected |
Y |
Y |
Y |
|
public |
Y |
Y |
Y |
Y |
类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
构造方法:
权限修饰符:private,默认的,protected,public
成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
除此以外的组合规则:
成员变量:public static final
成员方法:
public static
public abstract
public final
内部类:在一个类的内部定义类,即为内部类
内部类中可以直接访问外部类的成员,包括私有,因为内部类可以获得外部类的引用Outer.this
外部类要访问内部类的成员,必须创建对象
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
当成员内部类使用private修饰,则无法在别的类中直接进行使用,但我们可以在成员内部类所在的类中定义public方法访问成员内部类
静态成员内部类:static修饰
成员内部类被静态修饰后的访问方式,相当于外部类名调用内部静态成员,习惯把new提前
外部类名.内部类名 对象名 = 外部类名.内部类对象;
Outer.Inner oi = new Outer.Inner();
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(?); num,输出30
System.out.println(??); this.num,输出20
System.out.println(???); Outer.this.num,输出10
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
局部内部类:定义在方法内的类
public class Demo {
public static void main(String[] args) {
}
public OutReturn test(){
class T implements OutReturn{
@Override
public void hello(){
}
}
return new T();
}
}
jdk8以前,局部内部类访问其所在方法的局部变量时,该变量必须是final修饰的自定义常量
原因:
1.生命周期不同:方法执行结束出栈时,局部变量销毁,但是局部内部类对局部变量的引用依然存在,当局部内部类需要使用该局部变量时,就会出现非法引用
2.数据不同步:内部类并不是直接使用局部变量,而是通过自己的构造备份到内部,表面上看是一个变量,实际上并不是,假如局部内部类对该变量做了修改,那么实际上该局部变量在局部内部类外的值不会改变,这就很尴尬,加上final就可以阻止这样的事发生(无法对final重新赋值),对于jdk8,会默认加上final,不需要显式处理
匿名内部类:内部类的简化写法
前提:存在一个类或者接口,这个前提很重要,因为你不能让不存在的类匿名,也不能匿名继承普通的类,这里的类可以是具体类也可以是抽象类
格式
new 类名或者接口名(){
重写方法;
}
后面可以直接跟.方法名调用对象的成员方法
本质:一个继承该类或者实现该接口的,子类匿名对象
匿名的作用是为了调用方法,只调用一次就成为垃圾的那种,因为被调用的方法就是该匿名类要重写的方法,所以匿名内部类针对的是重写一个方法并调用,如果需要调用多个方法,那就要多个匿名对象