static final常量
- 必须声明同时被初始化
- 类名点来访问,不能被改变
- 建议:常量名所有字母都大写,多个单词用_分隔
- 编译器在编译时会将常量直接替换为具体的数,效率很高
- 何时使用:数据永远不变,且经常使用
抽象类
- 由abstract修饰
- 包含抽象类的方法必须是抽象类
- 抽象类不能被实列化(new 对象)
- 抽象类是需要被继承的
抽象类的意义
- 封装共有的属性和行为---->代码复用
- 为所有的派生类提供统一的类型--->向上造型
- 可以包含抽象方法,为所有的派生类提供统一的入口(能点出来的),派生类的行为不同,但入口相同,同时相当于强制重写
抽象方法
- 由abstract修饰
- 只有方法的定义,没有具体的实现(连{}都没有)
问:抽象方法存在的意义是什么? |
答:保证当发生向上造型时,通过超类的引用能点出来那个方法 |
问:既然意义在于能点出来,那为什么不设计为普通方法呢? |
答:若设计为普通方法,则派生类可以重写也可以不用重写,而设计为抽象方法可以强制派生类必须重写 |
接口
- 接口是一种引用数据类型
- 由关键字interface定义
- 只能包含常量和抽象方法
- 接口不能被实列化(new对象)
- 接口是需要被实现(继承)的,派生类:必须重写写所有抽象方法
- 一个类可以实现多个接口,用逗号分开,若又继承又实现时,应先继承后实现
- 接口可以继承接口
- 接口的意义:实现的多继承
关系 | |||
类与类 | 继承extends | ||
接口与接口 | 继承extends | ||
类和接口 | 实现implements |
设计规则
- 将所有派生类所共有的属性和行为,抽到超类中---->抽共性
- 若对象的行为都一样,设计为普通方法,若对象的行为都不一样,设计为抽象方法
- 将部分派生类所有共有的属性和行为,抽到接口中,接口是对继承的单根性扩展-->实现多继承
多态
- 同一类型的引用指向不同类型时,若不同的实现,所有抽象方法都是多态
- 同一个对象被造型为不同类型时,若不同的功能,所有对象都是多态
多态存在的三个必要条件
1.继承 :派生类继承超类的继承关系
2.重写 :子类需要在超类中的一些方法进行重写,然后调用方法时就会调用派生类重写的方法
3.向上造型:超类引用指向子类对象,将派生类对象类型转换成超类类型
多态的优点:
- 简化性
- 灵活性
- 接口性
- 可扩充性
- 可替换性
- 消除类之间的耦合关系
public class TestDemo {
public static void main(String[] args) {
boy b = new boy();
System.out.println(b.sum);
b.eat();
b.play();
Person p = new boy();
System.out.println(p.sum);
p.eat();
p.play();
}
}
class Person{
int sum = 1314;
public void eat(){
System.out.println("吃饭啦");
}
public static void play(){
System.out.println("玩游戏啦");
}
}
class boy extends Person{
int sum = 520;
@Override
public void eat(){
System.out.println("小智要吃冰淇淋!");
}
public static void play(){
System.out.println("小智玩小火龙");
}
}
自动类型转换
-
超类型的引用指向派生类的对象
-
能造型成为的数据类型有:超类+所实现的接口
强制类型转换
- 引用所指向的对象,就是该类型
- 引用所指向的对象,实现了该接口或继承了该类
- 强制时若不符合如上条件,则会发生发生ClassCastException类型转换异常 建议:在强转之前先通过intanceof 判断引用对象是否是该类型
内部类
局部内部类
类名称 对象名 = new 类名称();
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
public class Person {
String name = "小周";
static int age = 22;
public static void show() {
System.out.println("调用外部类中的show方法");
}
public void play() {
System.out.println("调用外部类中的play()方法");
}
public void () {
String name = "小周";
double height = 52.0;
//局部内部类 可以访问方法外部类中属性和方法
class Inner{
String name = "小文";
public void showInner(String name) {
show();
printf();
System.out.println(age);
System.out.println(height);
System.out.println("这是:"+Person.this.name);
System.out.println("这是:"+name);
System.out.println("这是:"+this.name);
}
}
//局部内部类 创建对象 要在方法内部 局部内部类的外部声明
Inner inner=new Inner();
inner.showInner(name);
}
public static void main(String[] args) {
Person person = new Person();
person.demo();
}
}
成员内部类
在内部方法内创建的类就是成员内部类
- 不能存在任何static的变量和方法
- 依赖于外部类,只有先创建外部类才能创建内部类
person boy=new person(); Inner inner=person.new Inner();
- 成员内部类可以无条件访问外部类的所有成员的属性和方法
- 同名属性名方法名时,访问外部类 外部类.this.成员名
person.this.name
public class Person {
String name = "小周";
static int age = 22;
public static void show() {
System.out.println("调用外部类中的show方法");
}
public void play() {
System.out.println("调用外部类中的play()方法");
}
public void boy() {
String name = "小周";
double height = 52.0;
//局部内部类 可以访问方法外部类中属性和方法
class Inner{
String name = "小文";
public void showInner(String name) {
show();
play();
System.out.println(age);
System.out.println(height);
System.out.println("这是:"+Person.this.name);
System.out.println("这是:"+name);
System.out.println("这是:"+this.name);
}
}
//局部内部类 创建对象 要在方法内部 局部内部类的外部声明
Inner inner=new Inner();
inner.showInner(name);
}
public static void main(String[] args) {
Person person = new Person();
person.boy();
}
}
静态内部类
静态内部类以static关键字修饰的类型
- 创建静态内部类是不需要依赖外部类,可以直接创建
- 静态内部类不可以使用外部类的非static成员方法和变量,而内部类则可以
public class Outer {
private int outerVariable = 1;
private int commonVariable = 2;
private static int outerStaticVariable = 3;
static {
System.out.println("Outer的静态块被执行了……");
}
/*成员方法*/
public void outerMothod() {
System.out.println("我是外部类的outerMethod方法");
}
/*静态方法*/
public static void outerStaticMethod() {
System.out.println("我是外部类的outerStaticMethod静态方法");
}
/* 静态内部类*/
public static class Inner {
/* 成员信息*/
private int innerVariable = 10;
private int commonVariable = 20;
static {
System.out.println("Outer.Inner的静态块执行了……");
}
private static int innerStaticVariable = 30;
/* 成员方法*/
public void innerShow() {
System.out.println("innerVariable:" + innerVariable);
System.out.println("内部的commonVariable:" + commonVariable);
System.out.println("outerStaticVariable:"+outerStaticVariable);
outerStaticMethod();
}
/*静态方法*/
public static void innerStaticShow() {
//被调用时会先加载Outer类
outerStaticMethod();
System.out.println("outerStaticVariable"+outerStaticVariable);
}
}
/*外部类的内部如何和内部类打交道*/
public static void callInner() {
System.out.println(Inner.innerStaticVariable);
Inner.innerStaticShow();
}
}
匿名内部类
- 匿名内部类是没有访问修饰符的
- 匿名内部类必须继承一个抽象类或者实现一个接口
- 匿名内部类不能存在任何静态成员或方法
- 匿名内部类没有构造方法,因为没有类名
public class Person {
public void boy() {
//匿名内部类,实现的是show接口
new show() {
public void play() {
System.out.println("阳光帅气小男孩");
}
}.play();
}
//匿名内部类必须继承或实现一个已有的接口
public interface show {
public void play();
}
public static void main(String[] args) {
Person person = new Person();
person.boy();
}
}