java基础学习之面向对象高级知识(三)

面向对象高级部分

继承性

继承的实现

继承性严格来讲就是扩充一个类已有的功能。

  • extends应该翻译为扩充,为了方便理解,称其为继承;
  • 子类又被称位派生类;
  • 父类又被称为超类;

继承的基本实现

// An highlighted block
class Person{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
class Student extends Person{

}
public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setName("张三");
        stu.setAge(20);
        System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge());
    }
}
执行结果:姓名:张三,年龄:20

在子类中扩充方法

// An highlighted block
class Person{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
class Student extends Person{
    private String school;

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}
public class Demo {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setName("张三");
        stu.setAge(20);
        stu.setSchool("山东大学");
        System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge()+",学校:"+stu.getSchool());

    }
}

执行结果:姓名:张三,年龄:20,学校:山东大学

继承的限制

限制一:Java不允许多重继承,但是允许多层继承

// An highlighted block
错误示例:
class A{}
class B{}
class C extends  A,B {}

// An highlighted block
多层继承
class A{}
class B extends  A {}
class C extends  B {}
C类实际上属于(孙)子类,这样一来就相当于B类继承了A类的全部方法,而C类又继承AB类的方法,这种操作称为多层继承。

限制二:子类在继承父类时,严格来讲会继承父类中的全部操作,但是对于所有私有操作属于隐式继承,而所有的非私有操作属于显式继承。

// An highlighted block
class A{
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}
class B extends A{}
public class Demo {
    public static void main(String[] args) {
        B b = new B();
        b.setMsg("张三");
        System.out.println(b.getMsg());
    }
}
执行结果:张三
B类里面不能针对msg属性进行直接访问,因为它在A类中属于私有声明,只能利用getMsg或setMsg间接访问

限制三:在子类对象构造前一定会默认调用父类的构造(默认使用无参构造),以保证父类的对象先实例化,子类对象后实例化。

// An highlighted block
class A{
    public A() {
        System.out.println("A类构造方法");
    }
}
class B extends A{
    public B() {
        System.out.println("B类构造方法");
    }
}
public class Demo {
    public static void main(String[] args) {
        new B();
    }
}
执行结果:A类构造方法
		 B类构造方法

上面代码虽然实例化的是子类对象,但是发现它会默认先执行父类构造,调用父类构造的方法体执行,再实例化子类对象并且调用子类的构造方法。对于子类的构造而言,就相当于隐含了super()的语句调用,由于super()主要调用父类的构造方法,所以必须放在子类构造方法的首行。
子类隐含语句

// An highlighted block
class B extends A{
    public B() {
    	super();	//父类中有无参构造时,加与不加无区别,如果编写则必须出现在首行
        System.out.println("B类构造方法");
    }
}

父类不提供无参构造方法

// An highlighted block
class A{
    public A(String title) {	//父类提供的有参构造方法
        System.out.println("A类构造方法,title="+title);
    }
}
class B extends A{
    public B(String title) {	//子类提供有参构造
        super(title);			//明确调用父类构造,否则将出现编译错误
        System.out.println("B类构造方法");
    }
}
public class Demo {
    public static void main(String[] args) {
        new B("hello");
    }
}
执行结果:A类构造方法,title=hello
		 B类构造方法

覆写

方法的覆写

没有实现方法覆写

// An highlighted block
class A{
    public void fun(){
        System.out.println("A类中的fun()方法");
    }
}
class B extends A{
}
public class Demo {
    public static void main(String[] args) {
        new B().fun();
    }
}
执行结果:A类中的fun()方法

实现方法覆写

// An highlighted block
class A{
    public void fun(){
        System.out.println("A类中的fun()方法");
    }
}
class B extends A{
    @Override
    public void fun() {
        System.out.println("B类中的fun()方法");
    }
}
public class Demo {
    public static void main(String[] args) {
        new B().fun();
    }
}

执行结果:B类中的fun()方法

定义更多的子类

// An highlighted block
class A{
    public void fun(){
        System.out.println("A类中的fun()方法");
    }
}
class B extends A{
    @Override
    public void fun() {
        System.out.println("B类中的fun()方法");
    }
}
class C extends A{
    @Override
    public void fun() {
        System.out.println("C类中的fun()方法");
    }
}
public class Demo {
    public static void main(String[] args) {
        new B().fun();
        new C().fun();
    }
}

执行结果:B类中的fun()方法
		 C类中的fun()方法

覆写权限问题:被子类覆写的方法不能拥有比父类更严格的访问控制权限
例如:如果父类的方法是default(默认),那么子类覆写方法时候只能使用default或者public,注意pirvate的方法不能被覆写。

// An highlighted block
class A{
     void fun(){
        System.out.println("A类中的fun()方法");
    }
}
class B extends A{
    @Override
    public void fun() {					//此时子类中的方法权限与父类相比更加宽松
        System.out.println("B类中的fun()方法");
    }
}

利用super方法访问父类中的方法

// An highlighted block
class A{
     void fun(){
        System.out.println("A类中的fun()方法");
    }
}
class B extends A{
    @Override
    void fun() {
        super.fun();
    }
}
public class Demo {
    public static void main(String[] args) {
        new B().fun();

    }
}
执行结果:A类中的fun()方法

属性的覆盖

如果子类定义了和父类完全相同的属性名称时,就称位属性的覆盖。

// An highlighted block
class A{
    String info = "hello";
}
class B extends A{
    int info = 10;			//名称相同,发生属性覆盖
    void fun() {
        System.out.println(super.info);
        System.out.println(this.info);
        System.out.println(info);
    }
}
public class Demo {
    public static void main(String[] args) {
        new B().fun();

    }
}

执行结果:hello
		 10
		 10

注意:在任何开发中,属性一般使用private封装,那么一旦封装后属性覆盖时没有任何意义的,因为父类定义的私有属性子类根本就看不见,更不会相互影响了。

this与super的区别

NO.区别thissuper
1功能调用本类构造、本类方法、本类属性子类调用父类构造、父类方法、父类属性
2形式先查找本类中是否存在有指定的调用结果,如果有则直接调用,如果没有则调用父类定义不查找子类,直接调用父类操作
3特殊表示本类的当前对象

在开发中,对于本类或父类中的操作,强烈建议加上“this.”或者“super.”的标记,便于维护。

继承的执行顺序

class A {
    static {
        System.out.println("父类的静态代码块");
    }

    public A() {
        System.out.println("父类的构造方法");
    }
}
class B extends A{
    static {
        System.out.println("子类的静态代码块");
    }

    public B() {
        System.out.println("子类的构造方法");
    }
}

public class App 
{
    public static void main( String[] args )
    {
        B b = new B();
    }
}
结果:父类的静态代码块
	 子类的静态代码块
	 父类的构造方法
	 子类的构造方法

可以看出先执行静态代码块→父类构造方法→子类构造方法

继承案例

开发数组的父类

// An highlighted block
class Array{
    private int data[];
    private int foot;
    public Array(int len) {
        if(len > 0){
            this.data = new int[len];
        }else {
            this.data = new int[1];
        }
    }
    public boolean add(int num){
        if(this.foot < this.data.length){
            this.data[this.foot++] = num;		//this.foot++的值为0
            return true;
        }
        return false;
    }
    public int[] getData(){
        return this.data;
    }
}
public class Demo {
    public static void main(String[] args) {
        Array arr = new Array(3);
        System.out.println(arr.add(20)+"、");
        System.out.println(arr.add(10)+"、");
        System.out.println(arr.add(30)+"、");
        System.out.println(arr.add(100)+"、");	//不可以保存数据,返回false
        int [] temp = arr.getData();
        for(int x = 0; x < temp.length; x++){
            System.out.print(temp[x]+"、");
        }
    }
}
执行结果:truetruetruefalse201030

提示:以上代码存在缺陷,存粹只是举个例子而已。

开发排序类

// An highlighted block
class SortArray extends Array{
    public SortArray(int len){
        super(len);
    }
    public int[] getData(){
        java.util.Arrays.sort(super.getData());
        return super.getData();
    }
}
public class Demo {
    public static void main(String[] args) {
        SortArray arr = new SortArray(3);
        System.out.println(arr.add(20)+"、");
        System.out.println(arr.add(10)+"、");
        System.out.println(arr.add(30)+"、");
        System.out.println(arr.add(100)+"、");	//不可以保存数据,返回false
        int [] temp = arr.getData();
        for(int x = 0; x < temp.length; x++){
            System.out.print(temp[x]+"、");
        }
    }
}
执行结果:truetruetruefalse102030

开发反转类

反转类指的是进行数组数据取得时,可以实现数据的首尾交换。

// An highlighted block
class ReverseArray extends Array{
    public ReverseArray(int len){
        super(len);
    }
    public int[] getData(){
        int center = super.getData().length / 2;
        int head = 0;
        int tail =super.getData().length - 1;
        for(int i = 0; i < center; i++) {
            int temp = super.getData()[head];
            super.getData()[head] = super.getData()[tail];
            super.getData()[tail] = temp;
            head++;
            tail--;
        }
        return super.getData();
    }
}
public class Message {
    public static void main(String[] args) {
        ReverseArray reverseArray = new ReverseArray(5);
        reverseArray.add(10);
        reverseArray.add(20);
        reverseArray.add(30);
        reverseArray.add(40);
        reverseArray.add(50);
        reverseArray.reverse();
        for(int i = 0 ; i < reverseArray.getData().length ; i++) {
            System.out.println(reverseArray.getData()[i]);
        }
    }
}
执行结果:5040302010

final关键字

在Java中final称为终结器,可以使用final定义类、方法和属性。

  • 使用final定义的类不能再有子类,即:任何类都不能继承以final声明的父类。
// An highlighted block
final class A{			//此类不能够有子类
}
class B extends A{		//错误继承
}
  • 使用final定义的方法不能被子类所覆写
// An highlighted block
class A{			
	public final void fun(){}		//此方法不允许子类覆写
}
class B extends A{		
	public void fun(){}		//此处不允许覆写
}
  • 使用final定义的变量就成了常量,常量必须在定义的时候设置好内容,并且不能修改。
// An highlighted block
class A{			
   final double AA = 10.1;
   public final void fun(){
   	AA = 1.1;				//不能修改常量
   }		
}

全局常量指的是利用了public static final 这3个关键字联合定义的常量。例如:public static final String MSG = “hello”;
需要记住的是,在定义常量时必须对其进行初始化赋值,否则将出现语法错误。

多态性

  • 方法的多态性:重载与覆写;
    重载:同一个方法名称,根据不同的参数类型及个数可以完成不同的功能;
    覆写:同一个方法,根据实例化的子类对象不同,所完成的功能也不同。

  • 对象的多态性:父子类对象的转换。
    向上转型:子类对象变为父类对象,格式:父类 父类对象 = 子类实例,自动转换;
    向下转换:父类对象变为子类对象,格式:子类 子类对象 = (子类)父类实例,强制转换;

B对象自动向上转型

// An highlighted block
class A{
    public void print(){
        System.out.println("A");
    }
}
class B extends A{
    @Override
    public void print() {
        System.out.println("B");
    }
}
class C extends A{
    @Override
    public void print() {
        System.out.println("C");
    }
}

public class App 
{
    public static void main( String[] args )
    {
        A a = new B();		//实例化的是子类对象,对象向上转型
        a.print();
    }
}
执行结果:B

此时,该引用只能访问子类继承或重写父类的方法,而不能直接访问子类特有的方法。

对象向下转型

// An highlighted block
public class TestDemo {
    public static void main(String[] args) {
        A a = new B();		//实例化的是子类对象,对象向上转型
        B b = (B)a;			//对象需要强制性地向下转型
        b.print();
    }
}
执行结果:B

因为有强制性转换的操作,所以向下转型操作本身是有前提条件的,即必须发生向上转型后才可以发生向下转型。

错误的向下转型

// An highlighted block
public class TestDemo {
    public static void main(String[] args) {
        A a = new A();
        B b = (B)a;
        a.print();
    }
}
执行结果:Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B at TestDemo.main(TestDemo.java:16)

如果两个没有关系的类对象强制发生向下转型时会带来类转换异常。所以向下转型是会存在安全隐患的,应尽量避免。

向上转型作用分析

// An highlighted block
class A{
    public void print(){
        System.out.println("A");
    }
}
class B extends A{
    @Override
    public void print() {
        System.out.println("B");
    }
}
class C extends A{
    @Override
    public void print() {
        System.out.println("C");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        A a1 = new B();
        A a2 = new C();
        fun(a1);
        fun(a2);
    }
    public static void fun(A a){		//方法中参数类型只能是一个可以包含B类和C类的的统一类型
        a.print();
    }
}
执行结果:BC

由以上可知,向上转型的主要目的是统一调用的参数类型。

向下转型,调用子类中的特殊功能

// An highlighted block
class A{
    public void print(){
        System.out.println("A");
    }
}
class B extends A{
    @Override
    public void print() {
        System.out.println("B");
    }
    public void msg(){
        System.out.println("B类中的扩充方法");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        A a = new B();
        fun(a);
    }
    static void fun(A a){
        B b = (B)a;
        b.msg();
    }
}
执行结果:B类中的扩充方法

instanceof关键字
instanceof关键字可以判断某一个对象是否是指定类的实例。

// An highlighted block
对象 instanceof 类	返回boolean 型 		//是返回true,否则返回false



public class TestDemo {
    public static void main(String[] args) {
        A a = new B();      //对象向上转型
        System.out.println(a instanceof A);
        System.out.println(a instanceof B);
        System.out.println(null instanceof A);
    }
}
执行结果:true
		 true
		 false

向下转型时建议使用instanceof判断下

// An highlighted block
class A{
    public void print(){
        System.out.println("A");
    }
}
class B extends A{
    @Override
    public void print() {
        System.out.println("B");
    }
    public void msg(){
        System.out.println("B类中的扩充方法");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        A a = new B();      //对象向上转型
        fun(a);
    }
    static void fun(A a){
        if(a instanceof B){
            B b = (B)a;
            b.msg();
        }
    }
}
执行结果:B类中的扩充方法

抽象类

抽象类定义

抽象类就是指在普通类的结构里面增加抽象方法的组成部分,抽象方法指的是没有方法体的方法,同时抽象方法还必须使用abstract关键字进行定义。。拥有抽象方法的类一定属于抽象类,抽象类要使用abstract声明。

定义抽象类

// An highlighted block
abstract class A{
    public void print(){
        System.out.println("A");
    }
    public abstract void fun();
}

注意:抽象类不能直接实例化对象(因为有抽象方法,但是抽象方法没有方法体,怎么可能去调用?)

使用抽象类,需要遵循一下原则:

  • 抽象类必须有子类,即每一个抽象类一定要被子类所继承,但是在Java中每一个子类只能够继承一个抽象类,所以具备单继承局限;
  • 抽象类的子类(子类不是抽象类)必须覆写抽象类中的全部抽象方法(强制子类覆写);
  • 依靠对象的向上转型概念,可以通过抽象类的子类完成抽象类的实例化对象操作。
// An highlighted block
abstract class A{
   public void print(){
       System.out.println("A");
   }
   public abstract void fun();
}
class B extends A{
   @Override
   public void fun() {
       System.out.println("hello");
   }
}

public class TestDemo {
   public static void main(String[] args) {
       A a = new B();      //对象向上转型
       a.fun();
   }
}
执行结果:hello

抽象类的相关限制

  • 抽象类里面由于会存在一些属性,那么在抽象类中一定会存在构造方法,目的是为了属性初始化,并且子类对象实例化时依然满足先执行父类构造再调用子类构造的情况。
  • 抽象类不能使用final定义,因为抽象类必须有子类,而final定义的类不能有子类
  • 抽象类中可以没有任何抽象方法,但是只要是抽象类,就不能直接使用关键字new实例化对象
// An highlighted block
abstract class A{
   public void print(){
       System.out.println("A");
   }
}
class B extends A{
}

public class TestDemo {
   public static void main(String[] args) {
       A a = new B();      //对象向上转型
       a.print();
   }
}
执行结果:A
  • 抽象类中依然可以定义内部的抽象类,而实现的子类也可以根据需要选择是否定义内部类来继承抽象内部类
// An highlighted block
abstract class A{
   abstract class B{
       public abstract void fun();
   }
}
class X extends A{
   public void print(){
       System.out.println("访问:www.baidu.com");
   }
   class Y extends B{
       @Override
       public void fun() {
           System.out.println("方法覆写");
       }
   }
}

public class TestDemo {
   public static void main(String[] args) {
       X x = new X();      
       x.print();
       X.Y xy = x.new Y();
       xy.fun();
   }
}
执行结果:访问:www.baidu.com
   	     方法覆写
  • 外部抽象类不允许使用static声明,而内部的抽象类允许使用static声明,使用static声明的内部抽象类就相当于是一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。
// An highlighted block
abstract class A{
    static abstract class B{
        public abstract void fun();
    }
}
class X extends A.B{
    @Override
    public void fun() {
        System.out.println("访问:www.baidu.com");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        A.B ab = new X();
        ab.fun();
    }
}
执行结果:访问:www.baidu.com
  • 在抽象类中,如果定义了static属性或方法,就可以在没有对象的时候直接调用
// An highlighted block
abstract class A{
    public static void fun(){
        System.out.println("访问:www.baidu.com");
    }
}

public class TestDemo {
    public static void main(String[] args) {
        A.fun();
    }
}
执行结果:访问:www.baidu.com

隐藏抽象类子类

// An highlighted block
abstract class A{
    public abstract void print();
    private static class B extends A{
        @Override
        public void print() {
            System.out.println("访问:www.baidu.com");
        }
    }
    public static A getInstance(){
        return new B();
    }
}
public class TestDemo {
    public static void main(String args[]){
        A a = A.getInstance();
        a.print();
    }
}
执行结果:访问:www.baidu.com

抽象类的应用-模板设计模式

抽象类的最主要特点相当于制约了子类必须覆写的方法,同时抽象类中也可以定义普通方法,而且最为关键的是,这些普通方法定义在抽象类时,可以直接调用类中定义的抽象方法,但是具体的抽象方法内容就必须由子类提供。

// An highlighted block
abstract class A{
    public void fun(){
        this.print();
    }
    public abstract void print();
}
class B extends A{
    @Override
    public void print() {
        System.out.println(11);
    }
}
public class TestDemo {
    public static void main(String args[]){
        A a = new B();
        a.fun();
    }
}
执行结果:11

定义一个行为类

// An highlighted block
abstract class Action{
	public static final int EAT = 1;
	public static final int SLEEP = 5;
	public static final int WORK = 7;
	public void command(int flag){
		switch(flag){
		case EAT:
			this.eat();
			break;
		case SLEEP:
			this.sleep();
			break;
		case WORK:
			this.work();
			break;
		case EAT + WORK:
			this.eat();
			this.work();
			break;
		}
	}
	public abstract void eat();
	public abstract void sleep();
	public abstract void work();
}

定义描述机器人的行为子类

// An highlighted block
class Robot extends Action{
	public void eat(){
		system.out.println("机器人充电");
	}
	public void sleep(){	//此操作不需要但必须覆写,所以方法体为空
	}
	public void work(){
		system.out.println("机器人在工作");
	}
}

定义人的类

// An highlighted block
class Human extends Action{
	public void eat(){
		system.out.println("人在吃饭");
	}
	public void sleep(){	
		system.out.println("人在睡觉");
	}
	public void work(){
		system.out.println("人在工作");
	}
}

定义猪的类

// An highlighted block
class Pig extends Action{
	public void eat(){
		system.out.println("猪在吃食物");
	}
	public void sleep(){	
		system.out.println("猪在睡觉");
	}
	public void work(){
	}
}

测试类

// An highlighted block
public class TestDemo {
	public static void main(String args[]){
		fun(new Robot());
		fun(new Human());
		fun(new Pig());
	}
	public static void fun(Action act){
		act.command(Action.EAT);
		act.command(Action.SLEEP);
		act.command(Action.WORK);
	}
}
执行结果:机器人充电
		 机器人在工作		(省略)...

接口

接口的定义

如果一个类只是由抽象方法和全局常量组成的,那么将其定义为接口。所谓接口就是一个特殊的类,而且这个类里面只有抽象方法全局常量
定义接口

// An highlighted block
interface A{
	public static final String MSG = "HELLO";	
	public abstract void print();
}

接口的简化定义

// An highlighted block
interface A{
	String MSG = "HELLO";	//可以省略public static final,通过“接口名.常量名”进行访问
	public void fun();		//可以省略public abstract,通过接口引用或实现类引用访问
}
  • 接口中存在抽象方法,所以不能直接使用new进行实例化操作
  • 接口必须要有子类,但子类可以使用implements关键字实现多个接口,避免单继承局限
  • 接口的子类必须要实现接口中的全部抽象方法,否则需要将该类设置为抽象类
  • 接口的对象可以利用子类对象的向上转型进行实例化操作

实现接口

// An highlighted block
interface A{
	String MSG = "HELLO";
	public void fun();
}
interface B{
	public abstract void get();
}
class X implements A,B{
	public void fun(){
		system.out.println("A接口的抽象方法");
	}
	public void get(){
		system.out.println("B接口的抽象方法");
	}
}
public class TestDemo{
	public static void main (String args[]){
		X x = new X();
		A a = x;	//自动向上转型
		B b = x;	//自动向上转型
		a.fun();
		b.get();
		system.out.println(a.MSG)
	}
}
执行结果:A接口的抽象方法
		 B接口的抽象方法
		 HELLO

判断类型

// An highlighted block
interface A{
    String MSG = "heelo";
    public void fun ();
}
interface B{
    public void get();
}
class X implements A,B{
    @Override
    public void fun() {
    }
    @Override
    public void get() {
        System.out.println("B接口的抽象方法");
    }
}
public class Main {

    public static void main(String[] args) {
	// write your code here
        A a = new X();
        B b = new X();
        b.get();
        System.out.println(a instanceof A);
        System.out.println(b instanceof B);
    }
}
执行结果:B接口的抽象方法
true
true

如果一个子类既要继承抽象类又要实现接口,那么应该采用先继承extends后实现接口implements的顺序完成

// An highlighted block
interface A{
    public void fun ();
}
interface B{
    public void get();
}
abstract class C{
    public abstract void change();
}
class X extends C implements A,B{
    @Override
    public void fun() {
        System.out.println("A接口的抽象方法");
    }
    @Override
    public void get() {
        System.out.println("B接口的抽象方法");
    }
    @Override
    public void change() {
        System.out.println("C类的抽象方法");
    }
}

接口的多继承

// An highlighted block
interface A{
    public void funA();
}
interface B{
    public void funB();
}
interface C extends A,B{
    public abstract void funC();
}
class X implements C{
    @Override
    public void funA() {
        System.out.println("A接口的抽象方法");
    }
    @Override
    public void funB() {
        System.out.println("B接口的抽象方法");
    }
    @Override
    public void funC() {
        System.out.println("C类的抽象方法");
    }
}

在定义接口C时使用extends关键字继承了两个父接口,这就相当于C接口中一共定义3个抽象方法,所以在定义X子类时必须覆写3个抽象方法。

在接口里面定义抽象类

// An highlighted block
interface A{
    public void funA();
    abstract class D{
        public abstract void funD();
    }
}
class X implements A{
    @Override
    public void funA() {
        System.out.println("A接口的抽象方法");
    }
    class Y extends D{
        @Override
        public void funD() {
            //可以选择性继承
        }
    }
}

如果在一个接口内部使用static去定义一个内部接口,该接口就表示是一个外部接口

// An highlighted block
interface A{
    public void funA();
    static interface B{
        public void funB();
    }
}
class X implements A.B{
    @Override
    public void funB() {
        System.out.println("A接口的抽象方法");
    }
}

接口定义加强(jdk8新特性)

定义默认方法
➢如果现在要在接口中定义默认方法,那么该方法上必须使用default来进行定义。

interface IMessage{
    void print();
    default void fun(){
        System.out.println("这是一个默认方法");
    };
}
class Message implements IMessage{
    @Override
    public void print() {
        System.out.println("这是一个实现方法");
    }
}
public class Main {
    public static void main(String args[]) {
        Message m = new Message();
        m.print();
        m.fun();
    }
}
结果:这是一个实现方法
	 这是一个普通方法

重写默认方法

class Message implements IMessage{
    @Override
    public void fun() {
        IMessage.super.fun();	//调用IMessage接口中的默认方法
        System.out.println("重写默认方法");
    }
}

定义static方法
➢使用default定义普通方法,是需要利用实例化对象明确调用的。如果用户有需要还可以使用static定义方法,这样该方法就可以由接口名称直接调用。

interface IMessage{
    void print();
    static void fun(){
        System.out.println("这是static普通方法");
    };
}
public class Main {
    public static void main(String args[]) {
        IMessage.fun();		//直接通过接口来调用,不需要实例化对象
    }
}
结果:这是一个static方法

接口的实际应用-标准

在日常的生活中,人们会经常听到接口这一词,而最常见的就是USB接口。利用USB接口可以连接U盘、电脑等设备。
如果要进行代码开发,一定要首先开发处USB接口标准,因为有了标准后,计算机才可以去使用这些标准,设备厂商才可以设计USB设备。
定义USB标准

interface USB{
	public void start();
	public void stop();
}

定义计算机类

class Computer{
	public void plugin(USB usb){
		usb.start();
		usb.stop();
	}
}

在计算机类中提供一个plugin()方法,这个方法可以接收USB接口实例,这样不管有多少种USB设备(USB接口对应的子类)都可以插入计算机上进行工作。下面依据USB接口标准定义出两个子类。
定义U盘子类

class Flash implements USB{
	public void start(){
		system.out.println("U盘开始使用");
	}
	public void stop(){
		system.out.println("U盘停止使用");
	}
}

定义打印机

class Print implements USB{
	public void start(){
		system.out.println("打印机开始使用");
	}
	public void stop(){
		system.out.println("打印机停止使用");
	}
}

按照上述方式,可以准备几万个子类,并且这几万个子类都可以在电脑的plugin()方法上使用
测试代码

public class Main {
    public static void main(String args[]) throws Exception {
        Computer com = new Computer();
        com.plugin(new Flash());
        com.plugin(new Print()); 
    }
}
结果:U盘开始使用
	 U盘停止使用
	 打印机开始使用
	 打印机停止使用

接口的应用——工厂设计模式(Factory)

interface Fruit{
    public void eat();
}

class Apple implements Fruit{
    @Override
    public void eat() {
        System.out.println("吃苹果");
    }
}
public class Main {
    public static void main(String args[]) throws Exception {
        Fruit f = new Apple();
        f.eat();
    }
}
结果:吃苹果

上述例子是一个比较熟悉的结构,但是这样的作法真的合理么?
如果要确认一个代码的编写风格是否良好,应该遵循以下两个标准。
1.客户端(现在为主方法main)调用简单,不需要关注具体的细节
2.程序代码的修改,不影响客户端的调用,即使用者可以不去关心代码是否变更。

根据以下2个标准,就可以发现本程序设计上的问题。在取得接口实例化对象时明确地指明了要使用的子类“Fruit f = new Apple()”,如果扩充了子类,客户端就需要去修改。为了解决问题,即想办法让客户端只看见接口而不让其看见子类,就需要一个中间的工具类来取得接口对象。
增加一个工厂类过渡

interface Fruit{
    public void eat();
}

class Apple implements Fruit{
    @Override
    public void eat() {
        System.out.println("吃苹果");
    }
}
class Orange implements Fruit{
    @Override
    public void eat() {
        System.out.println("吃橙子");
    }
}
class Factory{
    public static Fruit getInstance(String className){
        if("apple".equals(className)){
            return new Apple();
        }else if("orange".equals(className)){
            return new Orange();
        }else {
            return null;
        }
    }
}
public class Main {
    public static void main(String args[]) throws Exception {
        Fruit f = Factory.getInstance("orange");
        f.eat();
    }
}
结果:吃橙子

接口的应用——代理设计模式(Proxy)

➢代理设计也是在java开发中使用较多的一种设计模式,所谓的代理设计就是指一个代理主 题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理,就好比在生活中经常使用到的代理上网那样,客户通过网络代理连接网络,由代理服务器完成用户权限,访问限制等与上网操作相关的操作
在这里插入图片描述在这里插入图片描述
代理设计模式实现

interface Network{
    void browse();
}
class Real implements Network{
    @Override
    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("检查用户是否合法");
    }
    @Override
    public void browse() {
        this.check();	//调用其他相关业务操作
        this.network.browse();	//调用真实上网操作
    }
}
public class Main {
    public static void main(String args[]) throws Exception {
        Network net = null;
        net = new Proxy(new Real());
        net.browse();
    }
}
结果:检查用户是否合法
	上网浏览信息

抽象类与接口的区别

在这里插入图片描述

Object类

有一种类是所有类的父类,这就是Object类。

Object类的基本定义

利用Object类来接收对象

class Book{
}
public class Main {
    public static void main(String args[]) throws Exception {
        Object book = new Book();
    }
}

Object类的方法
在这里插入图片描述

取得对象信息:toString()

class Book{
}
public class Main {
    public static void main(String args[]) throws Exception {
        Object book = new Book();
        System.out.println(book.toString());
    }
}
结果:Book@4554617c

对象比较:equals()

在Object类,默认的equals()方法比较的是两个对象的内存地址信息,而不是对象内容。

class Book{
    private String title;
    private double price;

    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }
    public boolean equals(Object obj){		
        if(this == obj){    //判断是不是自己
            return true;
        }
        if(obj == null){
            return false;
        }
        if(!(obj instanceof Book)){
            return false;
        }
        Book book = (Book) obj;
        if(this.title.equals(book.title) && this.price == book.price){
            return true;
        }
        return false;
    }
}
public class Main {
    public static void main(String args[]) throws Exception {
        Book book1 = new Book("aa", 79.9);
        Book book2 = new Book("aa", 79.9);
        System.out.println(book1.equals(book2));
    }
}
结果:true

Object类与引用数据类型

➢Object是所有类的父类,那么0bject类可以接收所有类的对象, 但是在Java设计的时候,考虑到引用数据类型的特殊性,所以0bject类实际上是可以接收所有引用数据类型的数据,这就包括了数组、接口、类。
接收数组数据
在这里插入图片描述
接收接口对象
Object除了可以接收数组对象外,接口对象也同样可以利用Object接收。
但是要记住,接口不会继承任何类,所以也不会继承Object。
在这里插入图片描述

内部类

在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类(也称方法内部类)、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。

成员内部类

// An highlighted block
class Outer{
	private String msg = "hello world";
	class Inner{
		public void print(){
			system.out.println(msg);
		}
	}
	public void fun(){
		new Inner().print();
	}
}
public class TestDemo{
	public static void main(String args[]){
		Outer out = new Outer();
		out.fun();
	}
}
执行结果:hello world

结论:这样做最大缺点在于:破坏了类的结构性。优点是可以轻松访问外部类中的私有属性。

访问内部类的私有属性

// An highlighted block
class Outer{
	private String msg = "hello world";
	class Inner{
		private String info = "你好";
		public void print(){
			system.out.println(msg); // 也可以使用Outer.this.msg表示
		}
	}
	public void fun(){
		Inner in = new Inner();
		system.out.println(in.info);
	}
}
public class TestDemo{
	public static void main(String args[]){
		Outer out = new Outer();
		out.fun();
	}
}
执行结果:你好

实例化内部类对象

// An highlighted block
class Outer{
	private String msg = "hello world";
	class Inner{
		public void print(){
			system.out.println(Outer.this.msg);
		}
	}
}
public class TestDemo{
	public static void main(String args[]){
		Outer.Inner in = new Outer().new Inner();
		in.print();
	}
}
执行结果:hello world

局部内部类(也称方法内部类)

在普通方法里面定义内部类

// An highlighted block
class Outer{
	private static String msg = "hello";
	public void fun(){
		class Inner{
			public void print(){
				system.out.println(Outer.this.msg);
			}
		}
		new Inner().print();
	}
}
public class TestDemo{
	public static void main(Srting args[]){
		new Outer().fun();
	}
}
执行结果:hello

访问方法中定义的参数或变量

  • 定义在方法内,作用范围也在方法内
// An highlighted block
class Outer{
	private static String msg = "hello";
	public void fun(int num){
		double score = 99.9; 
		class Inner{
			public void print(){
				system.out.println("属性"+Outer.this.msg);
				system.out.println("方法参数"+num);
				system.out.println("放大变量"+score);
			}
		}
		new Inner().print();
	}
}
public class TestDemo{
	public static void main(Srting args[]){
		new Outer().fun(100);
	}
}
执行结果:	属性hello
			方法参数100
			方法变量99.9

以下是JDK1.8版本之前的写法,在JDK1.8之后此限制取消了

// An highlighted block
class Outer{
	private static String msg = "hello";
	public void fun(final int num){
		final double score = 99.9; 
		class Inner{
			public void print(){
				system.out.println("属性"+Outer.this.msg);
				system.out.println("方法参数"+num);
				system.out.println("放大变量"+score);
			}
		}
		new Inner().print();
	}
}

匿名内部类

➢内部类指的是在一个类的内部定义了另外的类结构,利用内部类可以方便的实现私有属性的互相访问,但是内部类是需要明确的使用class进行定义的。而匿名内部类的是没有名字的内部类,但是其必须在抽象类或接口基础上才可以定义。

interface Message{
    void fun();     //接口默认使用public,可以不写
}
public class Main {
    public static void main(String args[]) throws Exception {
        act(new Message() {     //使用匿名内部类实例化接口对象
            @Override
            public void fun() {
                System.out.println("hello");
            }
        });
    }
    public static void act(Message msg){
        msg.fun();
    }
}
结果:hello

静态内部类

使用static定义的属性或方法是不受类实例化对象控制的,所以如果使用static定义内部类,它一定不可能受到外部类的实例化对象控制。
如果一个内部类使用static定义,那么这个内部类就变为一个“外部类”,并且只能访问外部类中定义的static操作。相当于定义一个外部类。

  • 静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,需要通过外部类对象实例
  • 静态内部类对象实例化时,可以不依赖外部类对象
  • 可以通过外部类.内部类.静态成员的方式,访问内部类中的静态成员
// An highlighted block
class Outer{
	private static String msg = "hello";
	static class Inner{
		public void print(){
			system.out.println(msg);
		}
	}
}

实例化"外部类"对象

// An highlighted block
class Outer{
	private static String msg = "hello";
	static class Inner{
		public void print(){
			system.out.println(Outer.msg);
		}
	}
}
public class TestDemo{
	public static void main(Srting args[]){
		Outer.Inner in = new Outer.Inner();
		in.print();
	}
}
执行结果:hello

基本数据类型包装类

➢为了方便用户的开发,专门给出了-组包装类, 来包装八种基本数据类型: byte (Byte) 、short (Short) . int (Integer) 、long (Long)、float (Float) 、double (Double)、char (Character) 、boolean boolean (Boolean)
➢但是以上给出的包装类又分为两种子类型:
➢对象型包装类(Object直接子类):Character、Boolean
➢数值型包装类(Number直接子类):Byte、Short、Integer、Long、Float、Double
➢Number是一个抽象类, 里面一共定义了六个操作方法: intValue()、 doubleValue0、 floatValue(、 byteValue0、 shortValue0、 longValue()。

在这里插入图片描述

装箱与拆箱操作

➢现在已经存在有基本数据类型与包装类类,那么这两种类型间的转换就通过以下方式定义:
➢装箱操作:将基本数据类型变为包装类的形式;
➢每个包装类的构造方法都可以接收各自数据类型的变量;
➢拆箱操作:从包装类之中取出被包装的数据;
➢利用从Number类中继承而来的一系列: xxxValue()方法完成。

用构造方法进行装箱

public class Main {
    public static void main(String args[]) throws Exception {
        Integer integer = new Integer(10);
        int value = integer.intValue();		//手动拆箱
        System.out.println(value);
    }
}
结果:10

用静态方法进行装箱

public class Main {
    public static void main(String args[]) throws Exception {
        Integer integer = Integer.valueOf(10);
        int value = integer.intValue();		//手动拆箱
        System.out.println(value);
    }
}
结果:10

自动装箱与自动拆箱操作

public class Main {
    public static void main(String args[]) throws Exception {
        Integer obj = 10;
        int value = obj;
        System.out.println(value);
    }
}
结果:10

数据类型的转换

➢使用包装类最多的情况实际上是它的数据类型转换功能上,在包装类里面提供有将String型数据变为基本数据类型的方法,使用Integer、 Double、 Boolean几个常用类做说明:
➢Integer类: public static int parselnt(String s); .
➢Double类: public static double parseDouble(String s);
➢Boolean类: public static boolean parseBoolean(String s);

将字符串变为int型数据

public class Main {
    public static void main(String args[]) throws Exception {
        String str = "123";     //字符串需要都是数字
        int i = Integer.parseInt(str);
        System.out.println(i);
    }
}
结果:123

将字符串变为double型数据

public class Main {
    public static void main(String args[]) throws Exception {
        String str = "10.3";     //字符串需要都是数字
        double i = Double.parseDouble(str);
        System.out.println(i);
    }
}
结果:10.3

将字符串变为boolean型数据

public class Main {
    public static void main(String args[]) throws Exception {
        String str = "True";     //大小写随便写,不要写错就好
        boolean i = Boolean.parseBoolean(str);
        System.out.println(i);
    }
}
结果:true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值