1.继承
class A{}
class B extends A{}
Java中只允许单继承,不允许多继承,即一个子类只能继承一个父类。
子类(也称派生类)不能直接访问父类中的私有成员,可以通过getter,setter方法访问。
子类对象在实例化之前会先默认调用父类中的构造方法,在实例化子类对象之前需要先将父类中的属性进行初始化。
方法覆写:子类定义了与父类同名的方法,但子类覆写的方法不能比父类方法有更严格的访问权限。
方法覆写时从private变为default是方法覆写吗?不是,是在子类中定义了一个新的方法。
属性的覆盖:子类若与父类声明相同名称的属性,则在子类中直接访问时采用就近原则,即先找到本类的属性,若此时想调用父类的属性,直接采用“super.属性”即可。
区别 | 重载 | 覆写 |
定义 | 方法名称相同、参数类型和个数不同 | 都相同 |
范围 | 发生在一个类中 | 发生在继承类中 |
2.super关键字
从子类中调用父类的构造方法、普通方法、属性。
子类中通过“super 方法()”的形式可以访问父类中相关方法。
3.final关键字
使用final声明的类不能有子类;
使用final声明的方法不能被子类覆写;
使用final声明的变量成为常量,不能被修改;
使用final声明变量的时候,要求全部字母大写,比如INFO;
如果一个程序中的变量使用public static final声明,则此变量称为全局常量;
4.抽象类
包含一个抽象方法的类必须是抽象类;
抽象类和抽象方法都要使用abstract关键字声明;
抽象方法只需声明不需实现;
抽象类必须被子类继承,子类(如果不是抽象类)必须覆写抽象类中的全部抽象方法;
abstract class A{//定义抽象类
public static final String name="GRACE";//全局常量
public abstract void print();//定义抽象方法
}
抽象类和普通类最大区别在于强制。在实际开发中,不建议子类继承普通类,而是继承抽象类。
抽象方法不要使用private声明。
5.接口
接口是一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成。
接口中的抽象方法必须定义成public访问权限,如果不写的话,也是public访问权限。
interface Imessage{//为了区分接口名称和类名称,通常接口名称前加I
public static final String NAME="message";
public abstract void print();
}
可以简化写成
interface Imessage{//为了区分接口名称和类名称,通常接口名称前加I
String NAME="message";
void print();
}
一个子类可以同时实现多个接口。
interface A{}
abstract class B{}
class X extends B implements A{}
6.对象的多态性
(1)向上转型:子类对象->父类对象 自动 90%
(2)向下转型:父类对象->子类对象 强制 3%
向上转型
class A{
public void fun1(){
System.out.println("A->fun1()");
}
}
class B extends A{
public void fun1(){
System.out.println("B->fun1()");
}
public void fun2(){
System.out.println("B->fun2()");
}
}
public class Test {
public static void main(String args[]){
B b=new B();
A a=b;
a.fun1();
}
}
--------------------------------------------
B->fun1()
向下转型
class A{
public void fun1(){
System.out.println("A->fun1()");
}
}
class B extends A{
public void fun1(){
System.out.println("B->fun1()");
}
public void fun2(){
System.out.println("B->fun2()");
}
}
public class Test {
public static void main(String args[]){
A a=new B();//向上转型
((B) a).fun2();//向下转型
}
}
--------------------------------------------
B->fun2()
注意⚠️在进行对象的向下转型前,首先必须发生对象的向上转型,否则会出现对象转换异常。
向上描述的是一些公共的特征,向下描述的是子类自己特殊的定义环境,但是向下转型并不是一件安全的事。因为在进行向下转型之前一定要首先发生向上转型。
7.instanceof关键字
a instanceof B //true or false
用来判断一个对象到底是哪个类的实例。
在今后的开发中,在进行对象的向下转型之前最好先进行判断之后再进行相应的转换操作,这样可以避免类型转换异常的出现。
在类的设计中,永远不要去继承一个已经实现好的类,只能继承抽象类或实现接口,因为一旦发生对象的向上转型关系后,所调用的方法一定是被子类所覆写过的方法。
8.抽象类与接口的应用
为抽象类实例化
abstract class A{
public abstract void fun();
}
class B extends A{
public void fun(){
System.out.println("B extends A");
}
}
public class Test{
public static void main(String args[]){
A a=new B();
a.fun();
}
}
--------------------------------------------
B extends A
为接口实例化
interface A{
public abstract void fun();
}
class messageimp implements A{
public void fun(){
System.out.println("messageimp implements Imessage");
}
}
public class Test{
public static void main(String args[]){
A msg=new messageimp();
msg.fun();
}
}
抽象类的实际应用——模板设计
abstract class Person{
private int age;
private String name;
public Person(String name,int age){
this.name=name;
this.age=age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void say(){
System.out.println(this.getContent());
}
public abstract String getContent();
}
class Student extends Person{
private float score;
public Student(String name,int age,float score){
super(name,age);
this.score=score;
}
public String getContent(){
return "name:"+super.getName()+" age:"+super.getAge()+" score:"+this.score;
}
}
class Worker extends Person{
private float salary;
public Worker(String name,int age,float salary){
super(name,age);
this.salary=salary;
}
public String getContent(){
return "name:"+super.getName()+" age:"+super.getAge()+" salary:"+this.salary;
}
}
public class Test{
public static void main(String args[]){
Person per1=new Student("lily",20,95);
Person per2=new Worker("mario",35,60.0f);
per1.say();
per2.say();
}
}
--------------------------------------------
name:lily age:20 score:95.0
name:mario age:35 salary:60.0
接口的实际应用——制定标准
interface USB{
public void start();
public void stop();
}
class Computer{
public static void plugin(USB usb){
usb.start();
System.out.println("USB设备工作");
usb.stop();
}
}
class Printer implements USB{
public void start(){
System.out.println("打印机开始");
}
public void stop(){
System.out.println("打印机停止");
}
}
class Flash implements USB{
public void start(){
System.out.println("flash开始工作");
}
public void stop(){
System.out.println("flash停止工作");
}
}
public class Test{
public static void main(String args[]){
Computer.plugin(new Printer());
Computer.plugin(new Flash());
}
}
--------------------------------------------
打印机开始
USB设备工作
打印机停止
flash开始工作
USB设备工作
flash停止工作
设计模式——工厂设计
interface Fruit{
public void eat();
}
class Apple implements Fruit{
public void eat(){
System.out.println("吃苹果");
}
}
class Orange implements Fruit{
public void eat(){
System.out.println("吃橘子");
}
}
class Factory{
public static Fruit getInstance(String className){
Fruit f=null;
if("apple".equals(className)){
f=new Apple();
}
if("orange".equals(className)){
f=new Orange();
}
return f;
}
}
public class Test{
public static void main(String args[]){
Fruit f=null;
f=Factory.getInstance(args[0]);
f.eat();
}
}
--------------------------------------------
设计模式——代理设计
代理设计指一个代理主题来操作真实主题,真实主题执行具体的业务操作,代理主题负责其他相关业务的处理。
定义一个上网接口,代理主题和真实主题同时实现此接口,然后由代理主题操作真实主题。
interface Network{
public void browse();
}
class Real implements Network{
public void browse(){
System.out.println("上网浏览信息");
}
}
class Proxy implements Network{
private Network network;
public Proxy(Network network){
this.network=network;
}
public void check(){
System.out.println("检查用户是否合法");
}
public void browse(){
this.check();
this.network.browse();
}
}
public class Test{
public static void main(String args[]){
Network net=new Proxy(new Real());
net.browse();
}
}
--------------------------------------------
检查用户是否合法
上网浏览信息
适配器设计
一个接口首先被一个抽象类实现(此抽象类一般称为适配器类),并在此抽象类中实现若干方法(方法体为空),在以后的子类中直接继承此抽象类,就可以有选择的覆写所需要的方法。因为采用了适配器这个中间环节,所以子类就不用必须实现接口中的全部方法,可以有选择的实现所需要的方法。
在图形界面编程的事件处理中经常使用此设计模式。
在图形界面的部分,将看到大量的事件监听接口,如果全部实现方法则肯定不方便,所以Java中将提供大量的适配器类供用户使用。
interface Windows{
public void open();//窗口打开
public void close();//窗口关闭
public void activated();//窗口活动
public void iconified();//窗口最小化
public void deiconified();//窗口恢复大小
}
abstract class WindowsAdaptor implements Windows{
//覆写方法,方法体为空
public void open(){};
public void close(){};
public void activated(){};
public void iconified(){};
public void deiconified(){};
}
class WindowsImpl extends WindowsAdaptor{
//有选择的实现需要的方法
public void open(){
System.out.println("open");
}
public void close(){
System.out.println("close");
}
}
public class Test{
public static void main(String args[]){
Windows win=new WindowsImpl();
win.open();
win.close();
}
}
9.一个抽象类中可以定义多个接口或抽象类,一个接口中也可以定义多个抽象类或接口。
10.抽象类和接口之间的关系
类的设计原则:
一个类不要去继承一个已经实现好的类,要么继承抽象类,要么实现接口,若都可使用,优先使用接口,避免单继承局限。
区别 | 抽象类 | 接口 |
定义 | 包含一个抽象方法的类 | 抽象方法和全局常量的集合 |
组成 | 构造方法、抽象方法、普通方法、变量、常量 | 常量、抽象方法 |
使用 | 继承extends | 实现implements |
关系 | 抽象类可以实现多个接口 | 接口不能继承抽象类,但允许继承多个接口 |
常见设计模式 | 模板设计 | 工厂设计、代理设计 |
实际 | 作为一个模板 | 作为一个标准或能力 |
特殊 | 一个抽象类可以包含多个接口,一个接口中可以包含多个抽象类 |
11.Object类
利用Object类可以实现参数的统一。
Java中所有的类都有一个公共的父类就是Object类。
一个设计良好的类应该覆写以下三个方法。
方法名称 | 描述 |
Public Boolean equals(Object obj) | 对象比较 |
Public int hashCode() | 取得hash码 |
Public String toString() | 对象打印时调用 |
object类在实际开发中的应用:
因为object类可以接受任意类型的引用类型,所以在很多的类库设计上都采用了object作为方法的参数,这样操作起来会比较方便。
11.包装类
装箱操作:将一个基本数据类型变成包装类(一般通过构造函数完成)
拆箱操作:将一个包装类变为基本数据类型。
手工装箱及拆箱
public class Test {
public static void main(String args[]) {
int x=30;//声明一个基本数据类型
Integer i=new Integer(x);//装箱
int temp=i.intValue();//拆箱
}
}
自动装箱及拆箱
public class Test {
public static void main(String args[]) {
Integer i=30;//自动装箱
int x=i;//自动拆箱
}
}