1.接口是面向功能开发的
接口的引入代码:
public class TestInterface {
public static void main(String[] args) {
//可以使用四种声明方式。
BadStudent badStudent = new BadStudent();
Student student = new BadStudent();
//下面的方式一定是存在多态的。有继承,有重写,父接口指向子类对象
Fightable fightable = new BadStudent();
fightable.fight("");
SmokeAble smokeAble =new BadStudent();
}
}
//需求,创建一个会打架的学生对象。
//学生只应该包含他所特有的功能,不能包括其他的功能,利于复用代码
class Student{
void study(){
}
}
class BadStudent extends Student implements Fightable,SmokeAble{
//实现父接口中的功能
@Override
public void fight(Object o) {
}
@Override
public void smoke() {
}
}
//**描述功能使用接口**
interface Fightable{
/**
* 子类需要实现当前对象把o揍一顿的功能。
* @param o
*/
void fight(Object o);
}
//描述吸烟的功能
interface SmokeAble{
/**
* 当前对象实现抽象的功能
*/
void smoke();
}
//中学生继承了学生
class MiddleStudent extends Student{
}
2.接口概念:是一种可以将某些功能,混合添加到某种类型的主类型中去的类型。
import java.util.Arrays;
/**
*冒泡排序
*/
public class TestSort {
public static void main(String[] args) {
int[] arr = {56,76,34,23,5,8,0,34,23,7};
System.out.println(Arrays.toString(arr));
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 对指定的数组进行冒泡排序
*/
public static void bubbleSort(int[] arr){
//如果传入的是一个空数组,不排
if(arr==null)return;
final int LEN=arr.length;
//如果数组的长度为0,不排
if(arr.length==0)return;
//外层循环控制趟数
for (int i = 0; i <arr.length-1; i++) {
//内层循环控制第i+1行元素的逐个比较
//如果整个内层循环里面的判断不成立,那么意味着所有后面相连的元素都大于等于前面的元素;
// 也就是说待排序区是个有序的序列了,可以结束循环了;
boolean flag=false;
for (int j = 0; j < arr.length-1-i; j++) {
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=true;
}
}
if(!flag)break;
}
}
}
import java.util.Arrays;
/**
* 手写内部比较器排序比较学生数组(先按年龄,年龄相同时按成绩)
*/
public class TestSort {
public static void main(String[] args) {
test();
}
//对学生数组进行排序,升序,先按照年龄排序,如果年龄相同,按照成绩升序排序
public static void bubbleSort(Student[] students){
if(students==null)return;
final int LEN=students.length;
if(students.length==0)return;
boolean flag=false;
for (int i = 0; i <LEN-1 ; i++) {
for (int j = 0; j < LEN-1-i; j++) {
if(students[j].compareTo(students[j+1])>0){
Student temp=students[j];
students[j]=students[j+1];
students[j+1]=temp;
flag=true;
}
}
if(!flag)break;
}
}
//创建一个测试方法用于测试学生数组排序用内部比较器排序
static void test(){
Student[] students={
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100))
};
System.out.println(Arrays.toString(students));
bubbleSort(students);
System.out.println(Arrays.toString(students));
}
//创建一个产生随机数的方法
static int getRandomNumber(int min,int max){
return (int)(Math.random()*(max-min)+min);
}
}
//创建按学生类
class Student implements Comparable{
private int age;
private int score;
//构造器
public Student(int age, int score) {
this.age = age;
this.score = score;
}
//访问器和修改器
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
//重写父类Object的toString()方法
@Override
public String toString() {
return "\nStudent{" +
"age=" + age +
", score=" + score +
'}';
}
//实现了内部比较器接口,按照接口的规则去实现
@Override
public int compareTo(Object o) {
//引用数据类型强制向下转换
Student s=(Student)o;
//当前对象的年龄和o的年龄进行比较
/*
if(age>s.getAge()){
return 1;
}else if(age<s.getAge()){
return -1;
}else{
//当前对象的年龄和o相同,进行分数的比较
if(score>s.getScore()){
return 1;
}else if(score<s.getScore()){
return -1;
}else{
return 0;
}
}
*/
//更好的实现
int result=age-s.getAge();
if(result==0){
return score-s.getScore();
}
return result;
}
}
//自定义的内部比较类接口。让对象实现了该接口,对象自身拥有了比较功能
interface Comparable{
/**
* 当前对象和o比较的方法
* @param o 被比较的对象
* @return 如果当前对象比o大,返回正数;如果相等,返回0;否则返回负数
*/
int compareTo(Object o);
}
import java.sql.BatchUpdateException;
import java.util.Arrays;
/**
* 手写外部比较器并比较学生数组(先按年龄,年龄相同时按成绩)
*/
public class TestSort {
public static void main(String[] args) {
test2();
}
//对学生数组进行排序,升序,先按照年龄排序,如果年龄相同,按照成绩升序排序
public static void bubbleSort(MyComparator com,Student[] arr){
if(arr==null)return;
final int COUNT=arr.length;
if(COUNT==0)return;
boolean flag=false;
for (int i = 0; i < COUNT-1; i++) {
//使用外部比较器对象com对数组相邻的两个元素逐个比较,根据比较结果决定是否交换。
for (int j = 0; j < COUNT-1-i; j++) {
if(com.compare(arr[j],arr[j+1])>0){
Student temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=true;
}
}
if(!flag)break;
}
}
//创建一个测试方法用于测试学生数组排序用内部比较器排序
static void test2(){
Student[] students={
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100))
};
System.out.println(Arrays.toString(students));
MyComparator com=new MyComparator();
bubbleSort(com,students);
System.out.println(Arrays.toString(students));
}
//创建一个生成随机数方法
public static int getRandomNumber(int min,int max){
return (int)(Math.random()*(max-min)+min);
}
}
//创建学生对象
class Student{
private int age;
private int score;
//构造方法
public Student( int age, int score) {
this.age = age;
this.score = score;
}
//访问和修改方法
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
//重写toString()方法
@Override
public String toString() {
return "\nStudent{" +
"age=" + age +
", score=" + score +
'}';
}
}
//自定义的外部比较器接口
interface Comparable{
/**
* o1和o2进行比较
* @param o1 比较的第一个对象
* @param o2 比较的第二个对象
* @return 如果o1大于o2返回整数,如果o1小于o2返回负数,否则返回0
*/
int compare(Object o1,Object o2);
}
//定义类实现外部比较器接口
class MyComparator implements Comparable{
@Override
public int compare(Object o1, Object o2) {
Student s1=(Student)o1;
Student s2=(Student)o2;
int result=s1.getAge()-s2.getAge();
if(result==0){
result=s1.getScore()-s2.getScore();
}
return result;
}
}
import java.util.Arrays;
/**
* JDK提供的内部比较器(排序学生数组先按年龄再按成绩)
*/
public class TestSort {
public static void main(String[] args) {
test3();
}
public static void test3(){
Student[] students={
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100))
};
//给这些学生按照年龄和成绩排序
Arrays.sort(students);//sort()方法也可以对引用类型进行排序,可以用内部比较器
System.out.println(Arrays.toString(students));
}
//定义一个生成随机的方法
public static int getRandomNumber(int min,int max){
return (int)(Math.random()*(max-min)+min);
}
}
//创建学生类
class Student implements Comparable{
private int age;
private int score;
//构造方法
public Student(int age, int score) {
this.age = age;
this.score = score;
}
//访问方法和修改方法
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
//重写toString方法
@Override
public String toString() {
return "\nStudent{" +
"age=" + age +
", score=" + score +
'}';
}
//自定义类实现内部比较器接口(要求,被排序的数组的类型,需要实现java.lang.Comparable 接口。)
@Override
public int compareTo(Object o) {
Student s=(Student)o;
int result = this.age-s.age;
if(result == 0){
result = this.score - s.score;
}
return result;
}
}
import java.util.Arrays;
import java.util.Comparator;
/**
*JDK提供的外部比较器(比较学生数组按年龄排序)
*/
public class TestSort {
public static void main(String[] args) {
test3();
}
public static void test3(){
Student[] students={
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100)),
new Student(getRandomNumber(10,15),getRandomNumber(60,100))
};
//给这些学生按照年龄排序
//创建外部比较器类型指向子类对象
Comparator comparator=new AgeComparator();
Arrays.sort(students,comparator);//sort()方法也可以对引用类型进行排序,可以用外部比较器,也可以用内部比较器
System.out.println(Arrays.toString(students));
}
//定义一个生成随机的方法
public static int getRandomNumber(int min,int max){
return (int)(Math.random()*(max-min)+min);
}
}
//创建学生类
class Student{
private int age;
private int score;
//构造方法
public Student(int age, int score) {
this.age = age;
this.score = score;
}
//访问方法和修改方法
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
//重写toString方法
@Override
public String toString() {
return "\nStudent{" +
"age=" + age +
", score=" + score +
'}';
}
}
//自定义类实现外部比较器接口
class AgeComparator implements Comparator{
//只根据学生的年龄进行降序排列
@Override
public int compare(Object o1, Object o2) {
Student s1=(Student)o1;
Student s2=(Student)o2;
return s2.getAge()-s1.getAge();
}
}
//外部比较器的方法**匿名内部类**的使用**部分代码**
//使用方法匿名内部类创建一个外部比较器对象。根据分数排序
//将子类对象的引用作为参数使用
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student)o1;
Student s2 = (Student)o2;
return s1.getScore() - s2.getScore();
}
};
//
Arrays.sort(students,comparator);
//也可以这样写
//之间将外部比较器的匿名子类对象作为实参传入
Arrays.sort(students,new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student)o1;
Student s2 = (Student)o2;
return s1.getScore() - s2.getScore();
}
});
接口总结
1.接口中只允许public static final 修饰的变量,而且public static final 可以缺省。
2.接口中的方法必须是public abstract 修饰的抽象方法,public abstract可以缺省。
3.类是描述对象的,接口是描述功能的,是面向功能开发的。(功能)
4.接口中通常包含了一组抽象方法,那么接口定义了一组规则,让子类去按照规则实现。
5.接口实现了设计和实现相分离。接口是设计的过程,表达的是要做什么,接口的子类是实现的过程。子类的实现是如何做的过程。
6.继承表达的是 is-a 的关系。实现接口表达的是 has-a 的关系。
7.Java只允许单继承,只能有一个直接的父类,但是可以实现多个接口,可以有多个直接的父接口,在一定成都上弥补了java不支持多继承的缺陷。
8.类实现接口使用关键字implements,后面跟接口的名字,可以一次实现多个接口,使用逗号分隔。
9.接口同样可以实现多态,父接口引用指向实现的子类对象,而且一定是存在多态的。
10.接口同样可以继承接口,使用关键字extends,可以继承多个接口,使用逗号分隔。
11.上述内容都是JDK1.8之前的要求,从JDK1.8开始接口进行了调整。
import java.util.Comparator;
/**
* 内部类学习(方法匿名内部类的学习)
* 提供了一种快速的创建某一个类或者是接口的子类对象的方式
*/
public class TestMethodAnonymus {
public static void main(String[] args) {
//创建Test的子类对象就使用一次
MyTest test=new MyTest();
test.test();
//使用方法匿名内部类来实现上面的功能
Test test1=new Test(){
@Override
void test() {
System.out.println("使用匿名重写了");
}
};
//方法调用
test1.test();
//使用方法匿名内部类创建抽象类的子类对象
AbsClass absClass=new AbsClass() {
@Override
void test() {
System.out.println("匿名子类方法重写测试");
}
};
//方法调用
absClass.test();
//使用方法匿名内部类创建接口的子类对象。
Comparator comparator=new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
};
}
}
class Test{
void test(){
System.out.println("123");
}
}
class MyTest extends Test{
@Override
void test() {
System.out.println("重写了test方法");
}
}
abstract class AbsClass{
abstract void test();
}
/**
* 内部类学习(实例成员内部类)
*/
public class TestInner {
public static void main(String[] args) {
//在其他的类中创建类的内部类对象
Outer outer=new Outer();
Outer.Inner inner=outer.getInner();
//先创建外部类的对象,再通过外部类的对象创建内部类的对象
//结论:实例成员外部类的对象是依赖于外部类对象的,必须先创建外部类对象,再创建内部类对象
Outer.Inner inner1=outer.new Inner();
Outer.Inner inner2=new Outer().new Inner();
}
}
//实例成员内部类
class Outer{
private int age;
Outer(){ }
void test(){
Inner inner=new Inner();
inner.test();
inner.num++;
}
Inner getInner(){
return new Inner();
}
//实例成员内部类,有4中成员方法权限
//内部类一般是只给外部类使用的,不希望别的类去使用
class Inner{
private int num;
private int age;
Inner(){}
void test(){
//访问内部类的成员变量
num++;
//外部类方法
Outer.this.age++;
}
}
}
/**
* 内部类的学习(静态成员内部类)
*/
public class TestStaticInner {
public static void main(String[] args) {
//没有创建外部类对象,直接创建静态内部类对象
Out.Inner inner=Out.getInner();
//两种创建静态成员内部类对象的方式
Out.Inner inner1=new Out.Inner();
}
}
class Out{
private int age;
static Inner getInner(){
return new Inner();
}
//静态成员内部类的对象是依赖于外部类的,不依赖于外部类的对象,
//可以不创建外部类对象就直接创建内部类对象。
//只能访问外部类的静态成员。不能访问实例成员
static class Inner{
void test(){
}
}
}
/**
* JDK1.8接口的调整
*/
public class TestInterface18 {
public static void main(String[] args) {
MyClass myClass=new MyClass();
myClass.test();
myClass.test1();
}
}
interface MyInterface{
public static final int MAX=10;
public abstract void test();
//JDK1.8之后允许给方法提供默认实现了
default void test1(){
System.out.println("123");
}
//允许类中定义静态方法,直接使用接口名调用
static void test3(){
System.out.println("defg");
}
}
class MyClass implements MyInterface{
//实现父类接口中的抽象方法
public void test(){
System.out.println("我是为了实现父类中的抽象方法的方法");
}
//重写父类中默认实现的方法
public void test1(){
MyInterface.test3();//举例调用父接口中的静态方法。使用接口名调用。
}
}
今日练习:
2:使用Arrays工具类,对一个学生数组【降序】排序,要求先按照年龄排序,如果年龄相同,再按照分数排序。要求使用Arrays.sort(Object[] objs)进行排序。并打印排序结果
3:使用 Arrays.sort(Object[] objs, Comparator com) 对一个Book[] 数组排序。
Book类自定义,属性:书名,价格,要求按照价格升序排序,如果价格相同使用名字升序排序。注意:名字是String类型,字符串如何比较呢,String类实现了内部比较器接口,所以具有内部比较的功能,使用字符串内部比较的功能即可比较。并总结字符串的排序规则是什么?要求外部比较器对象使用匿名内部类实现。
import java.util.Arrays;
import java.util.Comparator;
/**
*对书数组进行排序,先按价格再按名字
*/
public class SortBook {
public static void main(String[] args) {
sort();
}
public static void sort(){
Book[] books={
new Book("红楼梦",59),
new Book("西游记",49),
new Book("水浒传",69),
new Book("三国演义",69),
new Book("论语",49),
new Book("史记",89)
};
System.out.println(Arrays.toString(books));
//使用匿名内部类实现外部比较器对象
Comparator comparator=new Comparator(){
@Override
public int compare(Object o1, Object o2) {
Book s1=(Book)o1;
Book s2=(Book)o2;
int result=s1.getPrice()-s2.getPrice();
if(result==0){
//String类实现了内部比较器接口,所以具有内部比较的功能
return s1.getName().compareTo(s2.getName());
}
return result;
}
};
Arrays.sort(books,comparator);
System.out.println(Arrays.toString(books));
}
}
class Book{
private String name;
private int price;
//构造方法
public Book(String name, int price) {
this.name = name;
this.price = price;
}
//访问器和修改器
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
//重写toString方法
@Override
public String toString() {
return "\nBook{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}