DAY 9
回顾:
一 多态
1三个前提条件:
a:必须有继承关系
b:方法重写
c:必须有父类引用指向子类对象:向上转型
2多态中的成员访问特点:
a:成员变量:编译看左,运行看左
b:成员方法(非静态的):编译看左,运行看右
c:静态成员方法:编译看左,运行看左(静态方法不算方法重写,和类有关)
3多态的弊端
不能使用子类的特有功能:
要使用子类的特有功能:
a):创建子类的具体对象(虽然可以,但是从内存角度考虑,不好:耗费空间)
b):向下转型:将父类的引用强制转换为子类的引用
子类名 对象名= (子类名)父类引用 ;
二 抽象类:
1概念
是由于在一个类中存在一个抽象功能,所以必须用abstract去修饰当前的这个类
abstract class Animal{}
抽象类中不一定有抽象方法,如果一个类中有抽象方法,那么这个类一定是抽象类!
抽象类是不能直接实例化的:不能创建对象
抽象类的子类:具体类
抽象类的实例化:需要通过该抽象类的子类进行数据的初始化!抽象类多态
Animal a = new Cat() ; 抽象类多态形式
2抽象类的成员特点
成员变量:可以是自定义常量,也可以是变量
成员方法:可以抽象方法(没有方法体的方法),也可以是非抽象方法
构造方法:可以有无参构造/也可以有有参构造
3 abstract不能和哪些关键字共同使用
public或者protected(这两个 是可以使用的)
static
private
final
4:接口
创建对象:具体类对象(根据具体需求)
使用抽象类多态(次之)
使用接口多态(最常用的)
接口的表示方法:interface 接口名{} 接口名和类名的命名规则一样
接口的子实现类和接口的关系:implements实现
class 子实现类名implements 接口名{}
接口的子实现类:一定是一个具体类;子实现类是抽象类(没有意义)
接口不能直接实例化--->最终创建接口的对象就是通过子实现类来进行实例化
测试类
main(){
通过接口多态:
接口名 对象名 =new 子实现类名() ;
}
接口的成员特点:
成员变量:
变量是一个常量:默认修饰符:public static final
成员方法:默认修饰符:public abstract
接口中是不能有构造方法的;
DAY9
一 API 制作
1需要定义一个类工具类:ArrayTool数组工具类:给该类写上文档注释(每一个静态方法都需要使用文档注释)
2需要将该类的无参私有化,目的是为了让外界创建对象
3 ArrayTool中的成员方法全部用static修饰
4 测试完毕
针对ArrayTool来制作
打开dos---->javadoc -d 目标名(文件名) -author -version ArrayTool.java
public class ArrayDemo {
public static void main(String[] args) {
//定义一个数组,静态初始化
int[] arr = {24,69,80,57,13} ;
//遍历数组
ArrayTool.printArray(arr) ;
//获取数组中的最大值
int result = ArrayTool.getMax(arr) ;
System.out.println("result:"+result);
//查询577元素
int index = ArrayTool.getIndex(arr, 577) ;
System.out.println("index:"+index);
int index2 = ArrayTool.getIndex(arr, 57) ;
System.out.println("index2:"+index2);
}
}
该类是针对数组操作的一个工具类,里面有一些对数组操作的功能
/**@author TUTU
@version V1.0**/
public class ArrayTool {
//无参构造私有,目的为了不让外界其对象
private ArrayTool(){
}
/**
* 该方法是针对数组的遍历的方法,遍历的元素[元素1, 元素2, 元素, ....]
* @param
* arr :需要被遍历的数组
* */
public static void printArray(int[] arr){
System.out.print("[");
for(int x = 0 ; x < arr.length ; x ++){
if(x==arr.length-1){
System.out.println(arr[x]+"]");
}else{
System.out.print(arr[x]+", ");
}
}
}
/**
* 该方法是针对数组获取最大值的方法
* @param
* arr :需要被遍历的 数组,可以获取每一个元素
* @return
* 返回的就是数组中最大值
*
* */
public static int getMax(int[] arr){
//定义参照物
int max = arr[0] ;
//遍历其他索引
for(int x = 1 ; x < arr.length ;x ++){
//判断
if(arr[x]>max){
max = arr[x] ;
}
}
return max ;
}
/**
该方法是查询数组中的元素在数组中第一次出现的索引
@param
arr : 需要查询的数组
@param
value:需要被查找的远古时
@return
如果查到了当前索引对应的元素,那么就直接返回当前索引,如果查不到,则返回-1
* */
public static int getIndex(int[] arr,int value){
//假设法
//定义一个索引:假设查不到
int index = -1 ;
//遍历数组
for(int x = 0 ; x < arr.length ; x ++){
//判断:如果刚好查到的x索引对应的元素和value相等,那么返回该索引
if(arr[x]==value){
//表查到了
//给索引遍历重新赋值
index = x ;
break ;
}
}
return index ;
}
}
二 形式参数和返回值研究
1 如果形式参数是引用类型:
具体类类:如果形式参数是一个具体类,那么需要创建该类对象
抽象类:如果形式参数是抽象类的情况,那么需要自定义一个抽象类的子类,来进行实例化(创建对象)
创建对象的实质:抽象类多态
接口:
//声明一个抽象类
abstract class Person{
public abstract void study() ;
}
//定义一个PersonDemo类
class PersonDemo{
//成员方法
//抽象类的多态
public void method(Person p) }
}
//自定义一个抽象的子类来进行Person的实例化
class Student2 extends Person{
public void study() {
System.out.println("good good study ,day day up!");
}
}
//测试类
public class PersonTest {
public static void main(String[] args) {
//需求:调用PersonDemo类中method()方法
//创建PersonDemo类的对象
new PersonDemo().method(new Student2()) ;//链式编程
}
}
2 返回值:
具体类:直接返回该类对象(通常实际开发中使用的是匿名对象)
抽象类:返回值如果是抽象类,需要的返回是该抽象类的子类对象
接口:
abstract class Person2{
public abstract void show() ;
}
//定义PersonDemo2类
class PersonDemo2{
public Person2 method(){ // 如果一个方法的返回值是一个抽象类,需要的返回是该抽象类的子类对象
return new Teacher() ;
}
//抽象类的子类
class Teacher extends Person2{
public void show() {
System.out.println("电子竞技没有爱情");
}
}
//测试类
public class PersonTest2 {
public static void main(String[] args) {
//需求:要调用PersonDemo2这个类中的method()方法
PersonDemo2 pd = new PersonDemo2() ;
Person2 p = pd.method() ;
p.show() ;
System.out.println("----------------");
//链式编程
Person2 p2 = new PersonDemo2().method() ;
p2.show() ;
}
}
三 内部类
在一个类中定义另一个类,那么把这种情况:内部类:
举例:在类A中定义一个类B,那么类B就是类A的内部类,同理,类A就是类B的外部类
内部类是直接可以访问外部类的成员,包括私有
外部类想要访问内部类的成员,必须通过创建内部类的对象访问该内部类的成员
//外部类
class Outer{
//外部类的成员变量
public int num = 100 ;
private int num = 20 ;
//内部类
class Inner{
//内部类的成员方法
public void show(){
System.out.println(num);
}
}
//外部类的成员方法
public void method(){ ;
//创建内部类对象
Inner i = new Inner() ;
i.show() ;
}
}
//测试类
public class InnerDemo {
public static void main(String[] args) {
}
}
2内部类的分类:
成员内部类:在外部类的成员位置
局部内部类:在外部了的局部位置定义的这个类
//外部类
class Outer2{
//外部类的成员变量
public int num = 100 ;
//成员内部类
/*class Inner2{
}*/
//外部类的成员方法
public void method(){
//局部位置
class Inner2{
}
}
3 成员内部类
在测试类中需要访问成员内部类中的成员的方法:
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
//外部类
class Outer3{
//定义外部类的变量
public int num = 10 ;
//成员内部类
class Inner3{
//内部类的成员方法(非静态的成员方法)
public void show(){
System.out.println(num);
}
}
}
//测试类
public class InnerDemo3 {
public static void main(String[] args) {
/**
* 需求:现在需要访问Inner3成员内部类中的show()方法
// 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer3.Inner3 oi = new Outer3().new Inner3() ;
//使用对象名调用show()方法
oi.show() ;
}
4 成员内部类的修饰符:
private :为了保证数的安全性
static修饰:为了方便调用.如果成员内部类被static修饰,那么要访问外部类的成员变量,这个变量必须被static修饰
5 静态的成员内部类访问该类中的成员方法:
格式:外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
class Body{
//成员内部类
private class Inner{
public void operator(){
System.out.println("心脏搭桥手术");
}
}
public void behivour(){
if("你是外科医生"){
Inner i = new Inner() ;
i.operator();
}
}
Body b = new Body();
b.behivour();
//外部类
class Outer4{
//外部类的两个成员变量
public static int num = 10 ;
public static int num2 = 20 ;
/** 对于静态的成员内部类来说,无论静态成员内部类中的成员方法是静态还是非静态的,要访问外部类的成员变量,该变量必须被static修饰
* */
//定义一个静态的成员内部类
public static class Inner4{
//非静态的内部类的成员方法
public void show(){
System.out.println(num);
System.out.println(num2);
}
//静态的内部类的成员方法
public static void show2(){
System.out.println(num);
System.out.println(num2);
}
}
}
//测试类
public class InnerDemo4 {
public static void main(String[] args) {
//需求:要访问静态成员内部类Inner4里面的show(),show2()方法
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
Outer4.Inner4 oi = new Outer4.Inner4() ;
oi.show() ;
oi.show2() ;//静态方法
System.out.println("--------------");
//show2()还有另外一种访问方式:
Outer4.Inner4.show2() ;
}
}
6 局部内部类:定义在外部类的局部位置
无论是局部内部类还是成员内部类(非静态的)都可以直接访问外部类的成员,包括私有
当前局部变量报错,必须用final修饰;是由于局部变量是随着方法调用而生成的,随着方法的调用完毕消失,而现在局部位置有一个局部内部类它要在自己的成员方法位置访问当前的局部变量必须把变量变成一个常量,(需要用final:自定义常量),这样的一个变量的值永远是固定的!
7 匿名内部类:是内部类的简化版格式
前提条件:必须存在一个接口或者是一个类(可以是具体类,也可以是一个抽象类)
书写的格式:
new 接口名或者类名(){
方法重写;
}
匿名内部类的实质:
继承了该类(抽象类)或者是实现了该接口的子类对象!
//定义一个接口
interface Inter{
//抽象功能
public abstract void show() ;
public abstract void show2() ;
}
//外部类
class Outer6{
//成员方法
public void method(){
使用接口名 对象名 = 匿名内部类的格式: new 接口名(){
//方法重写();
Inter i2 = new Inter() ;
Inter i = new Inter(){
@Override
public void show() {
System.out.println("show");
}
@Override
public void show2() {
System.out.println("show2");
}
};
//使用对象名调用
i.show();
i.show2() ;
}
}
//测试类
public class InnerDemo6 {
public static void main(String[] args) {
Outer6 o = new Outer6() ;
o.method() ;
}
}