03_java面向对象深入和数组

1、抽象方法和抽象类

1.1 基本概念

  • 抽象方法:使用abstract修饰的方法,只有声明,没有方法体(实现)。
  • 抽象类:包含抽象方法的类就是抽象类。
  • 抽象类存在的意义:定义的是一种规范,告诉子类必须要给抽象方法提供具体的实现,可以做到严格限制子类的这设计,是子类之间更加通用。
//抽象类
abstract class Animal {
	//抽象方法
	abstract public void cry();
}

1.2 抽象类的使用要点

  • 有抽象方法的类只能定义成抽象类。
  • 抽象方法只定义,不实现,但要求子类必须实现。
  • 抽象类不能使用new来实例化。
  • 抽象类只能用来被继承。
  • 抽象类可以包含属性、方法、构造方法。但构造方法不能用来new实例,只能用来被子类调用。
public class TestAbstract {
	public static void main(String[] args) {
//		Animal dog = new Animal();  //错误:抽象类不能实例化
		Animal dog = new Dog();
		//调用抽象方法时构造方法也会被调用
		dog.cry();  //叫......
		            //汪汪汪......
		dog.see();  //看门......
	}
}

//抽象类
abstract class Animal {
	//抽象方法
	abstract public void cry();
	
	int age;
	
	public Animal() {
		System.out.println("叫......");
	}
	
	public void see() {
		System.out.println("看门......");
	}
	
}

class Dog extends Animal {
	@Override
	public void cry() {
		System.out.println("汪汪汪......");
	}
}

2、接口

2.1 接口的基本概念

接口是比抽象类更抽象的抽象类,可以更加规范的对子类进行约束,实现了:规范和具体实现的分离。接口不提供任何实现,接口中的方法都是抽象方法。

2.2 定义接口

[访问权限修饰符] interface 接口名 [extends 父接口1,父接口2...] {
    常量定义;
    方法定义;
}

定义接口相关说明:

(1)访问权限修饰符:只能是public或默认;
(2)常量:接口中的属性只能是常量,总是由public static final 修饰,不写的话系统也会自动加上;
(3)方法:接口中的方法只能是抽象方法,总是由public abstract修饰,不写的话系统也会自动加上;
(4)接口可以多继承。

2.3 接口的实现

  • java中通过implements来实现接口。
  • 接口不能创建实例。
  • 一个类实现了接口,必须实现接口中的所有方法,并且这些方法只能是public的。
public class TestInterface {
	public static void main(String[] args) {
		Test t = new Student();
		t.study();
		t.play();
	}
}

//接口
interface Test {
	/*public static final*/ int MAX = 123;
	/*public abstract*/ void study();
	void play();
}

//实现类
class Student implements Test {
	@Override
	public void study() {
		System.out.println("学习");
	}

	@Override
	public void play() {
		System.out.println("玩");
	}
}

3、内部类

Java中内部类分为:成员内部类(非静态内部类、静态内部类)匿名内部类局部内部类

3.1 非静态内部类

非静态内部类特点:
  • 非静态内部类必须寄存在一个外部类对象中(非静态内部类依托外部类)。
  • 非静态内部类可以直接访问外部类成员,但外部类不能直接访问费静态内部类成员(提供一个很好的封装)。
  • 非静态内部类不能有静态方法、属性和初始化块。
非静态内部类成员变量访问要点:
  • 外部类属性:外部类名.this.变量名
  • 内部类属性:this.变量名
  • 内部类里方法的局部变量:变量名
  • 创建非静态内部类对象:
new 外部类().new 内部类()
public class TestInner {
	public static void main(String[] args) {
		//创建内部类对象
		Outer.Inner inner = new Outer().new Inner();
		inner.show();
	}
}

class Outer {
	int age = 15;
	
	//非静态内部类
	class Inner {
		int age  = 25;
		public void show() {
			int age = 35;
			System.out.println("内部方法的局部变量age = "  + age);
			System.out.println("内部类属性age = " + this.age);
			System.out.println("外部类属性age = " + Outer.this.age);
		}
	}
}

在这里插入图片描述

3.2 静态内部类

  • 静态内部类不依托于外部类。
  • 静态内部类可以看做外部类的一个静态成员。
  • 静态内部类不能访问外部类属性。
public class TestStaticInner {
	public static void main(String[] args) {
		//创建内部类对象
		Outer2.Inner2 inner2 = new Outer2.Inner2();
		inner2.show();
	}
}

class Outer2 {
	//静态内部类,相当于外部类的一个静态成员
	int age = 45;
	static class Inner2 {
		int age = 100;
		public void show() {
			int age = 36;
			System.out.println("内部方法的局部变量age = "  + age);
			System.out.println("内部类属性age = " + this.age);
			//静态内部类不能访问外部类属性
//			System.out.println("外部类属性age = " + Outer.this.age);
		}
	}
}

3.3 匿名内部类

  • 匿名内部类适合那种只需要使用一次的类。如:键盘监听操作等。
  • 匿名内部类没有访问权限修饰符。
  • 匿名内部类没有构造方法(因为它连名字都没有)。
  • 匿名内部类语法:
new 父类构造器() / 实现接口() {
	匿名内部类类体
}
public class TestAnonymousInner {
	
	public static void test(AA a) {
		a.aa();
	}
	
	public static void main(String[] args) {
		//匿名内部类
		TestAnonymousInner.test(new AA() {
			@Override
			public void aa() {
				System.out.println("TestAnonymousInner.main(...).new AA() {...}.aa()");
			}
		});
	}
}

interface AA {
	void aa();
}

3.4 局部内部类

  • 定义在方法内部的类,作用域只限于本方法。在实际开发中应用很少。
public class TestLocalInner {
	public void show3() {
		//局部内部类:只限于方法内部使用
		class Inner3 {
			public void fun() {
				System.out.println("TestLocalInner.show3().Inner3.fun()");
			}
		}
		new Inner3().fun();
	}
	
	public static void main(String[] args) {
		new TestLocalInner().show3();
	}
}

4、String

String类又称作不可变字符序列,位于java.lang中。

4.1 String类的基本用法

public class TestString {
	public static void main(String[] args) {
		String a1 = "";
		String a2 = "apple";
		String a3 = new String("apple");
		String a4 = "app" + "le";
		String a5 = "87" + 74;  //8774
		System.out.println(a2 == a4);  //true
		//比较字符串使用equals,比较内容是否相同
		System.out.println(a2.equals(a3));  //true
	}
}
java中常量池的分类:
  • 全局字符串常量池
  • class文件常量池
  • 运行时常量池

4.2 String类的常用方法

通过jdk api可以查看java中各个类所包含的方法。

public class TestString01 {
	public static void main(String[] args) {
		String s1 = "core Java";
		String s2 = "Core Java";
		//字符串长度
		System.out.println(s1.length());
		
		//提取字符串
		System.out.println(s1.charAt(6));  //提取下标为6的字符
		System.out.println(s2.substring(5));  //从下标为5开始提取字符
		System.out.println(s2.substring(0, 4));  //提取下标[0,4)的字符
		
		//比较字符串
		System.out.println(s1.equals(s2));  //区分大小写,false
		System.out.println(s1.equalsIgnoreCase(s2));  //不区分大小写,true
		
		//检测字符串是否包含某字符串
		System.out.println(s1.indexOf("Java"));  //区分大小写,包含返回字符串的开始下标,否则返回-1
		
		//替换字符串
		String s3 = s1.replace(" ", "&");
		System.out.println(s3);  //core&Java
		
		//判断字符串是否以某个字符串开头或结尾
		System.out.println(s3.startsWith("core"));  //true
		System.out.println(s3.endsWith("java"));  //false
		
		//大小写转换
		System.out.println(s1.toLowerCase());  //大写转小写,core java
		System.out.println(s1.toUpperCase());  //小写转大写,CORE JAVA
		
		//去掉字符串首尾的空格
		String s4 = "   Hello World!!!   ";
		System.out.println(s4.trim());  //Hello World!!!
		System.out.println(s4);  //   Hello World!!!   
	}
}

5、数组的拷贝、插入、删除以及Arrays工具类

5.1 数组拷贝

public class TestArrayCopy {
	public static void main(String[] args) {
		String[] c1 = {"aa","bb","cc","dd","ee"};
		String[] c2 = new String[5];
		System.arraycopy(c1, 1, c2, 2, 2);
		for (int i = 0; i < c2.length; i++) {
			System.out.println(i + " ---> " + c2[i]);
		}
	}
}

在这里插入图片描述

 System.arraycopy(src, srcPos, dest, destPos, length);

src:从哪个数组拷贝
srcPos:从哪个下标开始拷贝
dest:拷贝到哪个数组
destPos:从哪个下标开始存放
length:拷贝的长度

5.2 数组元素删除

  • 本质上也是数组的拷贝
    //c1表示需要操作的数组,index表示需要删除元素的下标
	public static String[] removeArray(String[] c1,int index) {
		System.arraycopy(c1, index+1, c1, index, c1.length-index-1);
		c1[c1.length-1] = null;
		for (int i = 0; i < c1.length; i++) {
			System.out.println(i + " ---> " + c1[i]);
		}
		return c1;
	}

5.3 数组元素插入

  • 先进行数组的扩容,然后拷贝元素,最后再将新的元素插入。
public static String[] insertArray(String[] c1,String str) {
	//数组扩容
	String[] c3 = new String[c1.length+1];
	//数组拷贝
	System.arraycopy(c1, 0, c3, 0, c1.length);
	//插入数组元素
	c3[c3.length-1] = str;
	for (int i = 0; i < c3.length; i++) {
		System.out.println(i + " ---> " + c3[i]);
	}
	return c3;
}

5.4 Arrays工具类

jdk提供的java.util.Arrays类,包含了常用的数字操作。

Array工具类常用的方法:
public class TestArrays {
	public static void main(String[] args) {
		int[] arr = {12,36,11,54,87,96,25};
		
		//打印数组
		System.out.println(Arrays.toString(arr));
		
		//排序(从小到大)
		Arrays.sort(arr);
		System.out.println(Arrays.toString(arr));
		
		//查找指定元素
		System.out.println(Arrays.binarySearch(arr, 12));
	}
}

5.5 多维数组

public class TestArray {
	public static void main(String[] args) {
		String[][] a1 = new String[2][3];
		for (String[] strings : a1) {
			System.out.println(Arrays.toString(strings));
		}
		System.out.println("#######################");
		int[][] a2 = {
				{100,200},
				{200,300,400},
				{300,400,500,600}
		};
		for (int[] is : a2) {
			System.out.println(Arrays.toString(is));
		}
	}
}

在这里插入图片描述

使用数组存储表格内容:
姓名性别民族年龄
张三汉族25
李四蒙古族36
王五哈萨克族17
public class Test2Array {
	public static void main(String[] args) {
		Object[] temp0 = {"姓名","性别","民族","年龄"};
		Object[] temp1 = {"张三","男","汉族",25};
		Object[] temp2 = {"李四","女","蒙古族",36};
		Object[] temp3 = {"王五","男","哈萨克族",17};
		
		Object[][] temps = new Object[4][];
		temps[0] = temp0;
		temps[1] = temp1;
		temps[2] = temp2;
		temps[3] = temp3;
		
		for (Object[] objects : temps) {
			System.out.println(Arrays.toString(objects));
		}
	}
}

6、常用的排序和查找算法

6.1 冒泡排序

  • 相邻元素进行比较
public static void Bubble(int[] a) {
	for (int i = 0; i < a.length-1; i++) {
		for (int j = 0; j < a.length-1-i; j++) {
			if (a[j] > a[j+1]) {
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
	}
	System.out.println(Arrays.toString(a));
}

6.2 二分法查找(折半查找)

基本思想:

1、首先将数组中的元素从小到大进行排序
2、将需要查找的值value与数组中间位置上的值midValue进行比较:

  • 如果value = midValue,检索成功;
  • 如果value > midValue,在数组后半部分继续进行二分法查找;
  • 如果value < midValue,在数组前半部分继续进行二分法查找;
  • 如果检索结束未找到,则检索失败。
public class BinarySearch {
	public static void main(String[] args) {
		int[] a = {2,5,4,1,6,3,9,8,7};
		System.out.println(Binary(a, 70));
	}
	
	public static int Binary(int[] a,int value) {
		//从小到大排序
		Arrays.sort(a);
		
		int low = 0;
		int high = a.length -1;
		while(low <= high) {
			int mid = (low + high) / 2;
			//检索成功
			if (value == a[mid]) {
				return mid;
			}
			//未检索到,继续检索
			if (value > a[mid]) {
				low = mid + 1;
			}
			if (value < a[mid]) {
				high = mid - 1;
			}
		}
		//检索失败
		return -1;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值