java之面向对象 1.面向对象与面向过程 2.类与对象及其使用 3.成员变量与局部变量区别 4.匿名对象 5.封装private 6.this与super关键字 7.构造器 8.static关键字 9.代码块 9.继承 10.final 11.多态 12.抽象类 13.接口 14.形式参数和返回值的问题深入研究 15.package 、import 关键字概述及作用 15.内部类

1.1面向过程(procedure oriented programming POP)

  刚开始接触C,它是一门面向过程思想的语言,写函数调函数是分析解决问题的步骤,就像小时候数学考试中的应用题一步一步算最后得到结果。

1.2面向对象(object oriented programming OOP)

  后来接触到JAVA,它是一门面向对象思想语言,当时从面向过程转换到面向对象的思想经过好处时间才转过来,面向对象简单理解为 具体的事物,如(person,dog,cat...)那么

这个对象能干什么用呢?我们分析一下,每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法)如(dog 状态 :颜色,品种,大小体重等等,行为:狗会跑,会啃骨头),java就是通过对象之间行为的交互来解决问题的。

面向对象就是把构成问题的事物分解成一个个对象,建立对象不是为了实现一个步骤,而是为了描述某个事物在解决问题中的行为。

类是面向对象中的一个很重要的概念,因为类是很多个具有相同属性和行为特征的对象所抽象出来的,对象是类的一个实例。

然后学java只做一件事:就是不断创建对象,使用对象,指挥对象,管理维护对象之间的关系。

1.3小结

面向过程:是一种以过程为中心的编程思想,强调步骤化的思考方式。

面向对象:管理维护对象之间的关系( 属性 就是该事物的描述信息      行为 就是该事物能够做什么)

2.类与对象及其使用

3.成员变量与局部变量区别

3.1成员变量和局部变量的区别?

A:在类中的位置不同
  成员变量:在类中方法外
  局部变量:在方法定义中或者方法声明上
B:在内存中的位置不同
  成员变量:在堆内存
  局部变量:在栈内存
C:生命周期不同
  成员变量:随着对象的创建而存在,随着对象的消失而消失
  局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
D:初始化值不同
  成员变量:有默认初始化值
  局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。

注意事项:
  局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。

3.2成员变量与局部变量定义

定义属性语法格式如下:

  [修饰符] 属性类型  属性名 [=默认值]

  • 成员变量 
    • 实例属性(不以static修饰)
    • 类属性(以static修饰)
  • 局部变量
    • 形参(方法签名中定义的变量)
    • 方法局部变量(在方法内定义)
    • 代码块局部变量(在代码块内定义)
class Varialbe {
    int num; //0
    public  static int number;//类属性,初始值为0
    public void show(int a ) {//a 局部变量方式1 不用显示初始化
        int num2 = 20;//局部变量方式2
        System.out.println("num2 = "+num2);
        System.out.println("a = "+ a);
    }
    {
        double  d = 20.2;//局部变量方式3
        System.out.println("d = "+ d);
    }
}
public class test7 {
    public static void main(String[] args) {
        Varialbe v = new Varialbe();
        System.out.println("成员非static = "+v.num); //访问成员变量
        System.out.println("类调用类属性 = "+Varialbe.number);
        System.out.println("对象调用类属性 ="+v.number);
        v.show(3);
    }
}

 3.3变量使用规则

变量什么时候定义为成员变量:
如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。

变量到底定义在哪里好呢?
变量的范围是越小越好。因为能及时的被回收。

4.匿名对象

/*
    匿名对象:就是没有名字的对象。
    
    匿名对象的应用场景:
        A:调用方法,仅仅只调用一次的时候。
            注意:调用多次的时候,不适合。
            那么,这种匿名调用有什么好处吗?
                有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。
        B:匿名对象可以作为实际参数传递
*/
class Student {
    public void show() {
        System.out.println("我爱学习");
    }
}

class StudentDemo {
    public void method(Student s) {
        s.show();
    }
}

class NoNameDemo {
    public static void main(String[] args) {
        //带名字的调用
        Student s = new Student();
        s.show();
        s.show();
        System.out.println("--------------");
        
        //匿名对象
        //new Student();
        //匿名对象调用方法
        new Student().show();
        new Student().show(); //这里其实是重新创建了一个新的对象
        System.out.println("--------------");
        
        
        //匿名对象作为实际参数传递
        StudentDemo sd = new StudentDemo();
        //Student ss = new Student();
        //sd.method(ss); //这里的s是一个实际参数
        //匿名对象
        sd.method(new Student());
        
        //在来一个
        new StudentDemo().method(new Student());
     }
}

5.封装private

private:是一个权限修饰符 ,可以修饰成员变量和成员方法 ,被其修饰的成员只能在本类中被访问

封装概述: 是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处: 隐藏实现细节,提供公共的访问方式 提高了代码的复用性 提高安全性。

封装原则: 将不需要对外提供的内容都隐藏起来。 把属性隐藏,提供公共方法对其访问。

6.this与super关键字

6.1分析this与super使用场景

     问题是:
         1.我不仅仅要输出局部范围的变量num,还要输出本类成员范围的变量num。怎么办呢?
         2.我还想要输出父类成员范围的变量num。怎么办呢?
             如果有一个东西和this相似,但是可以直接访问父类的数据就好了。
             恭喜你,这个关键字是存在的:super。
             
     this和super的区别?
         分别是什么呢?
             this代表本类对应的引用。
             super代表父类存储空间的标识(可以理解为父类的引用,可以操作父类的成员,但不是父类的对象!)
 
         怎么用呢?
             A:访问成员变量
                 this.成员变量     调用本类的成员变量
                 super.成员变量    调用父类的成员变量
             B:访问构造方法(在子父类的构造方法问题讲)
                 this(...)        调用本类的构造方法
                 super(...)       调用父类的构造方法
             C:访问成员方法(在子父类的成员方法问题讲)
                 this.成员方法     调用本类的成员方法
                 super.成员方法    调用父类的成员方法

 class Father {
     public int num = 10;
 }
 
 class Son extends Father {
     public int num = 20;
     
     public void show() {
         int num = 30;
         System.out.println(num);
         System.out.println(this.num);
         System.out.println(super.num);
     }
 }
 
 class ExtendsDemo5 {
     public static void main(String[] args) {
         Son s = new Son();
         s.show();
     }
}

 6.2this与super 区别及注意事项

  1)super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句) 

  2)this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
  3)super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名    super.成员函数据名(实参)

  4)this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)

  5)调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。

  6)super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。

  7)super()和this()均需放在构造方法内第一行。

  8)尽管可以用this调用一个构造器,但却不能调用两个。

  9)this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

  10)this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。

  11)从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

7.构造器

(1)作用:用于对对象的数据进行初始化
(2)格式:
A:构造器名和类名相同
B:没有返回值类型,也没有返回值,连void都不能有
C:修饰符可以省略,也可以是 public、protected、private其中之一
D:形参列表

思考题(1):构造方法中可不可以有return语句呢?
可以。而是我们写成这个样子就OK了:return;
其实,在任何的void类型的方法的最后你都可以写上:return;
思考题(2):如果为构造器定义了返回值,或使用void定义构造器没有返回值,编译时不会报错,但java会把这个所谓的构造器当成方法来处理。

(3)构造方法的注意事项
A:如果我们没写构造方法,系统将提供一个默认的无参构造方法
B:如果我们给出了构造方法,系统将不再提供默认构造方法
如果这个时候,我们要使用无参构造方法,就必须自己给出。
推荐:永远手动自己给出无参构造方法。
(4)给成员变量赋值的方式
A:setXxx()
B:带参构造方法

8.static关键字

8.1static的特点:

A:随着类的加载而加载

B:优先与对象存在

C:被类的所有对象共享,这其实也是我们判断该不该使用静态的依据。

D:可以通过类名调用,既可以通过对象名调用,也可以通过类名调用,建议通过类名调用。

E:修饰成员变量和成员方法

8.2静态的内存图

静态的内容在方法区的静态区


8.3静态的注意事项

A:在静态方法中没有this对象

如何理解呢?
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。

B:静态方法只能访问静态的成员变量和静态的成员方法
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
简单记:
静态只能访问静态。

8.4静态变量和成员变量的区别


A:所属不同
静态变量:属于类,类变量
成员变量:属于对象,对象变量,实例变量
B:内存位置不同
静态变量:方法区的静态区
成员变量:堆内存
C:生命周期不同
静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
D:调用不同
静态变量:可以通过对象名调用,也可以通过类名调用
成员变量:只能通过对象名调用

8.5 main方法的格式讲解:

public static void main(String[] args) {...}

public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。
static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。
void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。
main:是一个常见的方法入口。我见过的语言都是以main作为入口。
String[] args:这是一个字符串数组。值去哪里了?
这个东西到底有什么用啊?怎么给值啊?
这个东西早期是为了接收键盘录入的数据的。
格式是:
java MainDemo hello world java

class MainDemo {
    public static void main(String[] args) {
        //System.out.println(args); //[Ljava.lang.String;@175078b
        //System.out.println(args.length); //0
        //System.out.println(args[0]); //ArrayIndexOutOfBoundsException
        
        //接收数据后
        System.out.println(args); 
        System.out.println(args.length); 
        //System.out.println(args[0]); 
        for(int x=0; x<args.length; x++) {
            System.out.println(args[x]);
        }
    }
}

9.代码块

代码块:在Java中,使用{}括起来的代码被称为代码块。
根据其位置和声明的不同,可以分为
局部代码块:局部位置,用于限定变量的生命周期,限定变量生命周期,及早释放,提高内存利用率


构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。
作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。
静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。
作用:一般是对类进行初始化。

面试题?
静态代码块,构造代码块,构造方法的执行顺序?
静态代码块 -- 构造代码块 -- 构造方法
静态代码块:只执行一次
构造代码块:每次调用构造方法都执行

/*
    写程序的执行结果。
    
    林青霞都60了,我很伤心
    我是main方法
    Student 静态代码块
    Student 构造代码块
    Student 构造方法
    Student 构造代码块
    Student 构造方法
*/
class Student {
    static {
        System.out.println("Student 静态代码块");
    }   
    {
        System.out.println("Student 构造代码块");
    }    
    public Student() {
        System.out.println("Student 构造方法");
    }
}
class StudentDemo {
    static {
        System.out.println("林青霞都60了,我很伤心");
    }   
    public static void main(String[] args) {
        System.out.println("我是main方法");
        
        Student s1 = new Student();
        Student s2 = new Student();
    }
}

9.继承

9.1继承概述

继承概述:
把多个类中相同的内容给提取出来定义到一个类中。

如何实现继承呢?
Java提供了关键字:extends

格式:
class 子类名 extends 父类名 {}

好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类之间产生了关系,是多态的前提

类与类产生了关系,其实也是继承的一个弊端:
类的耦合性增强了。

开发的原则:低耦合,高内聚。
耦合:类与类的关系
内聚:就是自己完成某件事情的能力

9.2继承特点

A:Java只支持单继承,不支持多继承。
有些语言是支持多继承,格式:extends 类1,类2,...
B:Java支持多层继承(继承体系)

9.3继承注意事项

继承的注意事项:
A:子类只能继承父类所有非私有的成员(成员方法和成员变量)
B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
C:不要为了部分功能而去继承

9.4什么时候考虑使用继承呢?

继承其实体现的是一种关系:"is a"。
Person
Student
Teacher
水果
苹果
香蕉
橘子

采用假设法。
如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。

9.5继承中成员变量的关系?

继承中成员变量的关系:
A:子类中的成员变量和父类中的成员变量名称不一样,这个太简单。
B:子类中的成员变量和父类中的成员变量名称一样,这个怎么玩呢?
在子类方法中访问一个变量的查找顺序:
a:在子类方法的局部范围找,有就使用
b:在子类的成员范围找,有就使用
c:在父类的成员范围找,有就使用
d:如果还找不到,就报错。

9.6 this 与super 区别?

问题是:
我不仅仅要输出局部范围的num,还要输出本类成员范围的num。怎么办呢?
我还想要输出父类成员范围的num。怎么办呢?
如果有一个东西和this相似,但是可以直接访问父类的数据就好了。
恭喜你,这个关键字是存在的:super。

this和super的区别?
分别是什么呢?
this代表本类对应的引用。
super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)

怎么用呢?
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
B:调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法

9.7继承中构造方法的关系?

继承中构造方法的关系
A:子类中所有的构造方法默认都会访问父类中空参数的构造方法
B:为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。

注意:子类每一个构造方法的第一条语句默认都是:super();

如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
报错。
如何解决呢?
A:在父类中加一个无参构造方法
B:通过使用super关键字去显示的调用父类的带参构造方法
C:子类通过this去调用本类的其他构造方法
子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。

注意事项:
this(...)或者super(...)必须出现在第一条语句上。
如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。

9.8继承中测试题

测一:

看程序写结果:
A:成员变量 就近原则
B:this和super的问题
this访问本类的成员
super访问父类的成员
C:子类构造方法执行前默认先执行父类的无参构造方法
D:一个类的初始化过程
成员变量进行初始化
默认初始化
显示初始化
构造方法初始化

结果:
fu
zi
30
20
10
class Fu{
    public int num = 10;
    public Fu(){
        System.out.println("fu");
    }
}
class Zi extends Fu{
    public int num = 20;
    public Zi(){
        System.out.println("zi");
    }
    public void show(){
        int num = 30;
        System.out.println(num); //30
        System.out.println(this.num); //20
        System.out.println(super.num); //10
    }
}
class ExtendsTest {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}

测二:

看程序写结果:
A:一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块 > 构造代码块 > 构造方法
B:静态的内容是随着类的加载而加载
静态代码块的内容会优先执行
C:子类初始化之前先会进行父类的初始化

结果是:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi

class
Fu { static { System.out.println("静态代码块Fu"); } { System.out.println("构造代码块Fu"); } public Fu() { System.out.println("构造方法Fu"); } } class Zi extends Fu { static { System.out.println("静态代码块Zi"); } { System.out.println("构造代码块Zi"); } public Zi() { System.out.println("构造方法Zi"); } } class ExtendsTest2 { public static void main(String[] args) { Zi z = new Zi(); } }

测三:


看程序写结果:
A:成员变量的问题
int x = 10; //成员变量是基本类型
Student s = new Student(); //成员变量是引用类型
B:一个类的初始化过程
成员变量的初始化
默认初始化
显示初始化
构造方法初始化
C:子父类的初始化(分层初始化)
先进行父类初始化,然后进行子类初始化。

结果:
YXYZ

问题:
虽然子类中构造方法默认有一个super()
初始化的时候,不是按照那个顺序进行的。
而是按照分层初始化进行的。
它仅仅表示要先初始化父类数据,再初始化子类数据。

class X {
    Y b = new Y();
    X() {
        System.out.print("X");
    }
}

class Y {
    Y() {
        System.out.print("Y");
    }
}

public class Z extends X {
    Y y = new Y();
    Z() {
        //super()
        System.out.print("Z");
    }
    public static void main(String[] args) {
        new Z(); 
    }
}

9.9继承中的成员方法的关系:

继承中成员方法的关系:
A:子类中的方法和父类中的方法声明不一样,这个太简单。
B:子类中的方法和父类中的方法声明一样,这个该怎么玩呢?
通过子类对象调用方法:
a:先找子类中,看有没有这个方法,有就使用
b:再看父类中,有没有这个方法,有就使用
c:如果没有就报错。

9.10方法重写应用及注意事项:

方法重写应用?


方法重写:子类中出现了和父类中方法声明一模一样的方法。

方法重载:
本类中出现的方法名一样,参数列表不同的方法。与返回值无关。


子类对象调用方法的时候:
先找子类本身,再找父类。

方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。

案例:
A:定义一个手机类。
B:通过研究,我发明了一个新手机,这个手机的作用是在打完电话后,可以听天气预报。
按照我们基本的设计,我们把代码给写出来了。
但是呢?我们又发现新手机应该是手机,所以,它应该继承自手机。
其实这个时候的设计,并不是最好的。
因为手机打电话功能,是手机本身就具备的最基本的功能。
所以,我的新手机是不用在提供这个功能的。
但是,这个时候,打电话功能就没有了。这个不好。
最终,还是加上这个功能。由于它继承了手机类,所以,我们就直接使用父类的功能即可。
那么,如何使用父类的功能呢?通过super关键字调用



class
Phone { public void call(String name) { System.out.println("给"+name+"打电话"); } } class NewPhone extends Phone { public void call(String name) { //System.out.println("给"+name+"打电话"); super.call(name); System.out.println("可以听天气预报了"); } } class ExtendsDemo9 { public static void main(String[] args) { NewPhone np = new NewPhone(); np.call("林青霞"); } }

方法重写注意事项:

方法重写的注意事项
A:父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
B:子类重写父类方法时,访问权限不能更低
最好就一致
C:父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解

子类重写父类方法的时候,最好声明一模一样。

10.final

10.1 final 特点:

final可以修饰类,方法,变量

final可以修饰类,该类不能被继承。
final可以修饰方法,该方法不能被重写。(覆盖,复写)
final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。

常量:
A:字面值常量
"hello",10,true
B:自定义常量
final int x = 10;

10.2 final修饰局部变量问题

final修饰局部变量的问题
基本类型:基本类型的值不能发生改变。
引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。

10.3final 修饰变量初始化时机

A:被final修饰的变量只能赋值一次。
B:在构造方法完毕前。(非静态的常量)

11.多态

11.1多态概述

多态:同一个对象(事物),在不同时刻体现出来的不同状态。
举例:
猫是猫,猫是动物。
水(液体,固体,气态)。

多态的前提:
A:要有继承关系。
B:要有方法重写。
C:要有父类引用指向子类对象。

11.2多态中的成员访问特点:

多态中的成员访问特点:
A:成员变量
编译看左边,运行看左边。
B:构造方法
创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
C:成员方法
编译看左边,运行看右边。
D:静态方法
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)

由于成员方法存在方法重写,所以它运行看右边。

11.3多态的好处与弊端

多态的好处:
A:提高了代码的维护性(继承保证)
B:提高了代码的扩展性(由多态保证)

多态的弊端:
不能使用子类的特有功能。

我就想使用子类的特有功能?行不行?
行。
怎么用呢?
A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
B:把父类的引用强制转换为子类的引用。(向下转型)

对象间的转型问题:
向上转型:
Fu f = new Zi();
向下转型:
Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。

ClassCastException:类型转换异常
一般在多态的向下转型中容易出现

12.抽象类

12.1抽象类的规则:

A:抽象类和抽象方法必须用abstract关键字修饰

B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类

C:抽象类不能实例化
因为它不是具体的。
抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?
用于子类访问父类数据的初始化

D:抽象的子类
a:如果不想重写抽象方法,该子类是一个抽象类。
b:重写所有的抽象方法,这个时候子类是一个具体的类。
抽象类的实例化其实是靠具体的子类实现的。是多态的方式。

E:抽象类可以包含(属性,方法,构造器,初始化块,内部类,枚举)

属性:成员变量 即可以是变量,也可以是常量

方法:可以是普通方法和抽象方法

构造器:用于子类访问父类数据的初始化。

抽象方法: 强制要求子类做的事情。
非抽象方法: 子类继承的事情,提高代码复用性。

12.2abstract不能和那些关键字共存?

private 冲突   abstract修饰的方法必须被其子类重写才有意义,否则这个方法将永远不会有方法体
final 冲突  final修饰的类不能被继承,final修饰的方法不能被重写,因此final与abstract永远不能同时使用
static 无意义 static修饰属于类级别的 ,即没有所谓的类抽象方法

13.接口

13.1接口的定义

[修饰符]  interface 接口名 extends 父接口1,父接口2,,,{

  常量

  抽象方法

  内部类(内部接口)

  枚举

}

①修饰符   public/省略,如果省略了public,则默认采用包权访问控制符,即只有在相同包结构下才能可以访问该接口。

②接口里没有构造器和初始化块

③定义接口成员时,可以省略访问修饰符,如果指定修饰符,只能是public。

④成员变量 ,只能是常量,并且是静态的,默认修饰符:public static final

⑤只能是抽象方法,默认修饰符:public abstract

⑥定义内部类或者枚举类 ,默认修饰符:public static

⑦ 一个java源文件里可有多个没有修饰符的接口,但只能有一个public接口,并且文件名和接口名一致。

13.2 类与类 类与接口  接口与接口关系

类与类:
继承关系,只能单继承,可以多层继承。
类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。
接口与接口:
继承关系,可以单继承,也可以多继承。

13.3接口不能实例化的描述问题?

A:接口不能实例化
那么,接口如何实例化呢?
按照多态的方式来实例化。
B:接口的子类
a:可以是抽象类。但是意义不大。
b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

14.形式参数和返回值的问题深入研究

形式参数:

基本类型(太简单,不是我今天要讲解的)
引用类型:
类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
抽象类:需要的是该抽象的类子类对象
接口:需要的是该接口的实现类对象

返回值类型:

基本类型:(基本类型太简单,我不准备讲解)
引用类型:
类:返回的是该类的对象
抽象类:返回的是该抽象类的子类对象
接口:返回的是该接口的实现类的对象

15.package 、import 关键字概述及作用

15.1包的定义

包的定义
package 包名;
多级包用.分开即可

注意事项:
A:package语句必须是程序的第一条可执行的代码
B:package语句在一个java文件中只能有一个
C:如果没有package,默认表示无包名

包:
A:其实就是文件夹
B:作用
a:把相同的类名放到不同的包中
b:对类进行分类管理

15.2带包的编译和运行

带包的编译和运行:
A:手动式
a:编写一个带包的java文件。
b:通过javac命令编译该java文件。
c:手动创建包名。
d:把b步骤的class文件放到c步骤的最底层包
e:回到和包根目录在同一目录的地方,然后运行
带包运行。

B:自动式
a:编写一个带包的java文件。
b:javac编译的时候带上-d即可
javac -d . HelloWorld.java
c:回到和包根目录在同一目录的地方,然后运行
带包运行。

15.3导包 import

导包:
格式:import 包名;
这种方式导入是到类的名称。
注意:我们用谁就导谁。

面试题:
package,import,class有没有顺序关系?
有。
package > import > class

Package:只能有一个
import:可以有多个
class:可以有多个,以后建议是一个

15.内部类

15.1内部类的概述及作用:

内部类概述: 定义在其他类的内部的类就称为内部类。
内部类作用:①内部类提供了更好的封装,把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

      ②内部类成员可以直接访问外部类的私有数据,但外部类不能直接访问内部类的实现细节。

      ③外部类要访问内部类的成员,必须创建对象。

      ④匿名内部类适合用于创建那些仅需要一次使用的类。

      ⑤内部类修饰符 public 、protected、默认修饰符、private

      

 内部类里面的成员:

普通初始化块 

15.2内部类的位置

内部类位置
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类。(方法内定义内部类)

成员内部类:
如何直接访问内部类的成员。
外部类名.内部类名 对象名 = 外部类对象.内部类对象;

15.3外部类 内部类 内部类方法的局部变量 同名访问?

外部类变量:外部类类名.this.属性

内部类变量:this.属性

内部类里方法局部变量 :直接访问

java 不允许在非静态内部类里定义静态成员(静态方法、静态属性、静态初始化块)

15.4静态内部类

①修饰符:static修饰内部类,但static不可修饰外部类

②成员:静态成员、非静态成员

③访问外部类: 静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。

 

15.5局部内部类


局部内部类
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

面试题:
局部内部类访问局部变量的注意事项?
A:局部内部类访问局部变量必须用final修饰
B:为什么呢?
局部变量是随着方法的调用而调用,随着调用完毕而消失。
而堆内存的内容并不会立即消失。所以,我们加final修饰。
加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
我在内存中存储的是数据20,所以,我还是有数据在使用。



class
Outer { private int num = 10; public void method() { //int num2 = 20; //final int num2 = 20; class Inner { public void show() { System.out.println(num); //从内部类中访问本地变量num2; 需要被声明为最终类型 System.out.println(num2);//20 } } //System.out.println(num2); Inner i = new Inner(); i.show(); } } class InnerClassDemo5 { public static void main(String[] args) { Outer o = new Outer(); o.method(); } }

15.6匿名内部类 


匿名内部类
就是内部类的简化写法。


前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。

格式:
new 类名或者接口名(){
重写方法;
}

本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。


interface
Inter { public abstract void show(); public abstract void show2(); } class Outer { public void method() { //一个方法的时候 new Inter() { public void show() { System.out.println("show"); } }.show(); } } class InnerClassDemo6 { public static void main(String[] args) { Outer o = new Outer(); o.method(); } }

15.7匿名内部类多个方法调用方式

interface Inter {
    public abstract void show();
    public abstract void show2();
}

class Outer {
    public void method() {

        //二个方法的时候
        /*
        new Inter() {
            public void show() {
                System.out.println("show");
            }
            
            public void show2() {
                System.out.println("show2");
            }
        }.show();
        
        new Inter() {
            public void show() {
                System.out.println("show");
            }
            
            public void show2() {
                System.out.println("show2");
            }
        }.show2();
        */
        
        //如果我是很多个方法,就很麻烦了
        //那么,我们有没有改进的方案呢?
        Inter i = new Inter() { //多态
            public void show() {
                System.out.println("show");
            }
            
            public void show2() {
                System.out.println("show2");
            }
        };
        
        i.show();
        i.show2();
    }
}

class InnerClassDemo6 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}
匿名内部类在开发中的使用
interface
Person { public abstract void study(); } class PersonDemo { //接口名作为形式参数 //其实这里需要的不是接口,而是该接口的实现类的对象 public void method(Person p) { p.study(); } } //实现类 class Student implements Person { public void study() { System.out.println("好好学习,天天向上"); } } class InnerClassTest2 { public static void main(String[] args) { //测试 PersonDemo pd = new PersonDemo(); Person p = new Student(); pd.method(p); System.out.println("--------------------"); //匿名内部类在开发中的使用 //匿名内部类的本质是继承类或者实现了接口的子类匿名对象 pd.method(new Person(){ public void study() { System.out.println("好好学习,天天向上"); } }); } }

15.8匿名内部类面试题


匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”


interface
Inter { void show(); //public abstract } class Outer { //补齐代码 public static Inter method() { //子类对象 -- 子类匿名对象 return new Inter() { public void show() { System.out.println("HelloWorld"); } }; } } class OuterDemo { public static void main(String[] args) { Outer.method().show(); /* 1:Outer.method()可以看出method()应该是Outer中的一个静态方法。 2:Outer.method().show()可以看出method()方法的返回值是一个对象。 又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。 */ } }