欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java之面向对象

程序员文章站 2022-03-24 20:02:04
...

1.面向对象与面向过程

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()方法的返回值类型是一个接口。 */ } }