JAVA面向对象(四)——抽象类

抽象类

类似于C++中的虚函数(virtual)

抽象方法

​ 使用abstract修饰的方法,没有方法体,只有声明。定义是一种规范,就是要告诉子类必须要给抽象方法提供具体的实现。

抽象类

​ 包含抽象方法的类就是抽象类。通过abstract方法定义规范,然后要求子类必须定义具体实现。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用。

package cn.yhq.oop;

public abstract class Animal {

    //特点:1.没有实现。2.子类必须实现。
    //作用:提示子类必须用这个方法。
    abstract public void shout();

    public void run(){
        System.out.println("跑跑跑!");
    }

    public static void main(String[] args) {
        Animal a = new Animal(); //这里不能被new
        Animal b = new Dog();//但可以这样写
    }

}

class Dog extends Animal{
    @Override
    public void shout() {
        System.out.println("汪汪");
    }
}
使用要点
  • 有抽象方法的类只能定义成抽象类
  • 抽象类不能实例化,即不能用new来实例化抽象类
  • 抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用。
  • 抽象类只能用来被继承。
  • 抽象方法必须被子类实现

接口

​ idea中创建一个接口:右键点击New->Class->在class选项上选择Interface。

类似于C++中的.h文件,只有方法的声明,没有实现。

声明格式
[访问修饰符]interface 接口名 [extends 父接口1,父接口2...]{ //接口可以实现多继承
常量定义; //常量总是public static final修饰
方法定义;
}

注意:接口中不能定义变量,并且方法只能是public abstract

package cn.yhq.oop;

public class TestInterface {
    public static void main(String[] args) {
        Volant v = new Angel();//v不能调Honest方法
        v.fly();
        
        Honest h = new Angel();
        h.helpOther();

    }
}
interface Volant{
    int FLY_HEIGHT = 100;
    void fly();
}
interface Honest{
    void helpOther();
}
class Angel implements Volant,Honest{
    @Override
    public void fly() {
        System.out.println("飞飞飞");
    }

    @Override
    public void helpOther() {
        System.out.println("帮助他人");
    } //实现类可以实现多个类接口

}
接口多继承
interface A{
    void Amethod();
}
interface B{
    void Bmethod();
}
interface C extends A,B{
    void Cmethod();
}
class SubClass implements C{

    @Override
    public void Amethod() {

    }

    @Override
    public void Bmethod() {

    }

    @Override
    public void Cmethod() {

    }
}

内部类的分类

在类中定义类。

​ Java中内部类主要分为成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类。成员内部类(可以使用private、default、protected、public任意进行修饰)。类文件中的表示:外部类$内部类.class。

a).非静态内部类:

package cn.yhq.oop;

public class TestInnerClass {
    public static void main(String[] args) {
        //创建内部类对象
        Outer.Inner inner = new Outer().new Inner();//先创建外部类再创建内部类,注意:要new两次!!
        inner.show();
    }

}
class Outer{ //外部类不能使用内部类
    private int age = 10;
    public void tesyOuter(){
        System.out.println("这是Outer的一个方法");
    }
    class Inner{//非静态内部类,只为Outer服务
        //内部类中不能加静态这个属性
        int age = 20;
        public void show(){
            int age = 30;
            System.out.println("外部类的成员变量age:"+Outer.this.age);
            System.out.println("内部类的成员变量age:"+this.age);
            System.out.println("局部变量age:"+age);
        }
    }
}

b).静态内部类:

静态内部类可以看作外部类的一个静态成员。因此,外部类的方法中可以通过:“静态内部类.名字”的方式来访问静态内部类的静态成员,通过new静态内部类()访问静态内部类的实例。

public class TestStaticInnerClass {
    public static void main(String[] args) {
        Outer2.Inner2 inner = new Outer2.Inner2();
    }
}//静态类中不能调用外部类的this
//同理,静态内部类中只能调用外类中的静态变量和方法
class Outer2{
    static class Inner2{

    }
}

c).匿名内部类的使用

适合那种只需要使用一次的类。比如:键盘监听操作等。

语法:

new 父类构造器(实参类表)或接口(){
		//匿名内部类类体
}

例子:

this.addWindowListener(new WindowAdapter() {
      @Override
    public void windowClosing(WindowEvent e) {
            System.out.println("关闭程序");
            System.exit(0);
           }
   });
  //这个函数就是一个匿名内部类的例子,其中addWindowListener就是一个匿名内部类
class TestAnonymousInnerClass{
    public static void test01(AA a){
        a.aa();
    }
}
interface AA{
    void aa();
}

public static void main(String[] args) {
        TestAnonymousInnerClass.test01(new AA() {
            @Override
            public void aa() {
                System.out.println("匿名类调用");
            }
        });
    }

d).局部内部类

​ 定义在方法内部,作用域只限于本方法,称为局部内部类。

public class Test2{
	public void show(){
	//作用域仅限于该方法
	class Inner{
		public void fun(){
			System.out.printIn("Helloworld");
					}
		}
	new Inner().fun();
	}
	public static void main(){
		new Test2().show();
	}
}

String类

  • String类又称不可变字符串序列
  • String位于Java.lang包内,Java程序默认导入Java.lang包下的所有类
  • Java没有内置的字符串类型,而是在标准Java类库中提供一个预定义的类String,每个用双括号括起来的字符串都是String类的一个实例。

demo:

        String str10 = "YHQ";
        String str11 = "YHQ";
        String str12 = new String("YHQ");//这里创建了新的一个对象

        System.out.println(str10 == str11);//带双引号的字符串,编译器会将其拼接起来,然后放到常量池里面
        System.out.println(str12 == str11);//所以字符串比较使用equals()

在这里插入图片描述

String的比较使用equals

String常用的方法

在这里插入图片描述

在这里插入图片描述

数组深入

数组的拷贝
    public static void main(String[] args) {
        String[] s= {"a","b","c","d"};
        String[] s2 = new String[10];
        System.arraycopy(s,2,s2,6,3);
  //从S的第2个位置拷贝到s2第6个位置,拷贝三个元素
    //测试从数组中删除某个元素(本质还是数组的拷贝)
    public static void testBasicCopy2(){
        String[] s= {"a","b","c","d","e"};
       // String[] s2 = new String[10];
        System.arraycopy(s,3,s,3-1,s.length-3);
        s[s.length -1] = null;
        for (int i = 0;i<s.length;i++){
            System.out.println(i+"--"+s[i]);
        }
    }
    //数组扩容(先定义一个更大的数组,然后把原数组内容原封不动拷贝到新数组中)
    public static void extendRange(){
        String[] s1 = {"a","v","i"};
        String[] s2 = new String[s1.length+10];
        System.arraycopy(s1,0,s2,0,s1.length);//将s1中的元素拷贝到了s2
        for (String temp:s2){
            System.out.println(temp);
        }

    }
Arrays工具类
package cn.yhq.oop;
import java.util.Arrays;

public class TestArrays {
    public static void main(String[] args) {
        int[] a = {100,10,20,30,5};
        //System.out.println(a);
        System.out.println(Arrays.toString(a));
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
        System.out.println(Arrays.binarySearch(a,35));
    }
}
二维数组
package cn.yhq.oop;

import java.util.Arrays;

public class TestTableArr {
    //数组存储表格数据
    public static void main(String[] args) {
        Object[] emp1 = {100,"YHQ",19,"讲师","2003,1,13"};
        Object[] emp2 = {101,"YOP",19,"讲师","2003,1,13"};
        Object[] emp3 = {102,"YKI",19,"讲师","2003,1,13"};

        Object[][] tableData = new Object[3][];
        tableData[0] = emp1;
        tableData[1] = emp2;
        tableData[2] = emp3;
        for (Object[] temp:tableData){
            System.out.println(Arrays.toString(temp));
        }
    }
}
数组实例:二分法查找

先上自己写的代码,特点:冗余,空间占用率高

    public static int[] halfFind(int[] arr,int goal){
        int high = arr.length;
        int low = 0;
        int halfnum = ((high+low+1)/2)-1;
        int times = 0;
        while (true){
            if (arr[halfnum]<goal){
                low = halfnum;
                halfnum = (low+high)/2;
                times++;
            }else if (arr[halfnum] > goal){
                high = halfnum;
                halfnum  = (high+low)/2;
                times++;
            }
            if (arr[halfnum] == goal){
                System.out.println(goal+"在数组中的"+halfnum+"位置");
                break;
            }
            if (times > 3){
                System.out.println("查无此数"+"="+times);
                break;
            }
        }
        return arr;
    }

思路就是定义三个索引,分别指向中间和两端,根据算法的特点去计算这三个点的移动,然后循环结束条件是:判断循环次数是否达到了时间复杂度最高的情况,使用一个计数器进行计数。


别人代码

    public static int halfFind(int[] arr,int goal,int data){//data是用于方法重载的区别
        int low = 0;
        int high = arr.length-1;
        data = 1;
        while (low<=high){//由于low的自增性和high的自减性,始终会超过high
            int mid = (low+high)/2;
            if (goal == arr[mid]){
                return mid;
            }
            if (goal>arr[mid]){
                low = mid+1;
            }
            if (goal<arr[mid]){
                high = mid-1;
            }//基本实现其实是差不多的
        }
        return -1;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值