05Java类与对象

类与对象

事物: 类:

   属性 成员变量

   行为 成员方法

 类:是一组相关的属性和行为的集合。是一个抽象的概念。  学生:类

对象:是该类事物的具体表现形式。具体存在的个体。     班长:对象

1:面向对象思想

  面向对象是基于面向过程的编程思想。

  面向过程:强调的是每一个功能的步骤

  面向对象:强调的是对象,然后由对象去调用功能

2:面向对象的思想特点

  A:是一种更符合我们思想习惯的思想

  B:可以将复杂的事情简单化

  C:将我们从执行者变成了指挥者

3:开发,设计,特征

  面向对象开发:就是不断的创建对象,使用对象,指挥对象做事情。

  面向对象设计:其实就是在管理和维护对象之间的关系。

  面向对象特征:

封装(encapsulation)

继承(inheritance)

多态(polymorphism)

​ 抽象

类、对象、实例的关系

每个 对象 都是某个 (class)的一个 实例 (instance)。

对象是类实例化的结果 –> 类定义了一个数据类型,而对象是该数据类型的一个实例化。

类中的成员

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

  A:在类中的位置不同

    成员变量(属性,字段,域,全局变量):在类中方法外声明的变量。用于描述类的特征

    局部变量:在方法定义中或者方法声明上。

  B:在内存中的位置不同

    成员变量:在堆内存

    局部变量:在栈内存

  C:生命周期不同

    成员变量:随着对象的创建而存在,随着对象的消失而消失

    局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

  D:初始化值不同

    成员变量:有默认初始化值

    局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。

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

new关键字

在堆中开辟空间,创建类的实例(对象)。

类的每个对象都有自己的成员变量。

img

成员方法(函数)

​ 用于描述类的行为(动作)。

  i. 基本格式:

    访问权限 返回类型 方法名([参数列表]){

      代码;

    }

  ii. 当方法不需要返回类型时,使用void关键字表示。

  iii. return关键字:

    1. 结束方法。

    2. 返回数据。

方法的重载

  i. 同一个类中**,出现名字相同**,但参数列表不同(个数不同,顺序不同,类型不同)的现象。

  ii. 方法的重载与返回类型,访问权限无关。

  Override:方法重写

  Overload:方法重载

形参与实参

  i. 形参为基本数据类型:传递的是值,形参改变,实参不变

  ii. 形参为引用数据类型:传递的是引用,通常形参改变,实参也发生改变

可变长参数

​ JDK1.5开始出现。

  i. 只能用于形参。

  ii. 格式:数据类型… 参数名

  iii. 可变长参数的本质:一维数组

  iv. 如果方法有多个参数,可变长参数必须出现在最后。

构造方法

​ 又叫 构造器、构造函数。

  i. 构造方法的功能(作用):为类的成员变量初始化

  ii. 构造方法的特征:

    1. 构造方法的名字与类名相同(普通方法的名字也可以与类名相同)。

    2. 构造方法没有返回类型,没有具体的返回值,不能使用void关键字

  iii. 类一定有构造方法

  iv. 构造方法私有将无法创建对象

      public class Function {

        private Function(){}

      }

  v. 当没有在类中显式的写构造方法时,JVM会自动为类添加默认的无参构造方法

      默认构造方法:

        访问权限与类相同 构造方法名(){

      }

    当在类中显式的写了构造方法后,JVM不再为类添加默认的构造方法。

  vi. 通常,构造方法只能在new关键字后面调用。即构造方法在创建对象时被调用

  vii. 构造方法可以重载

  viii.

img

包(package)

  i. 包的本质就是文件夹。

  ii. 包的作用:

    1. 解决类的重名问题。

    2. 管理类。

  iii. 当类位于某个包中时,类的首行必须为package语句(注释除外)。

  iv. 当使用其它包中的类时,需要使用import语句导入类(导包)。

  v. java.lang包中的内容,JVM自动导入。

  vi. eclipse中直接创建在src(default package)下的类无法使用import语句导入。

  vii. JAVA命名规范:包名均为小写。oracle.jdbc.driver.OracleDriver

创建对象做了哪些事情

img

匿名对象

匿名对象:没有名字的对象。 //new Student();

  匿名对象的应用场景:

  A:调用方法,仅仅只调用一次的时候。

    这种匿名调用的好处:匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。

    new Student().show();

    new Student().show(); //这里其实是重新创建了一个新的对象

  B:匿名对象可以作为实际参数传递

    new StudentDemo().method(new Student());

private、this、super、static关键字

private

  i. 是一个权限修饰符

  ii. 可以修饰成员(成员变量和成员方法)。被private修饰的成员只能在本类中被访问。构造方法私有将无法创建对象。

this

  • 代表当前类的对象的引用

  • 引用当前类中的成员变量成员方法

  • 只能在构造方法中通过this来调用其他构造方法且要放在首行,普通方法中不能使用。

  • 不能通过this递归调用构造方法。

1
2
3
4
5
6
7
8
9
private String name;

public static void main(String[] args) {
this.name = "zhangsan"; // 错误,主方法是静态的,不能使用this关键字。
}

public String getName() {
return name; // 使用直接调用,其实是隐含的this。
}

super

代表父类存储空间的标识。(代表父类的引用,用来访问父类的成员)

  • 如果自己用super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行
  • 如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法
  • 如果子类构造方法中既没有显示调用父类的构造方法,而父类没有无参的构造方法,则编译出错

注意:super.getClass() 和 this.getClass() 返回的都是 new 对象时指定的类。

static

修饰成员变量和成员方法

静态的成员可以直接使用类名(接口名)直接调用,也可以通过类的对象调用。

    修饰成员变量:静态变量

      i. 类所有的对象共用一份静态变量。

      ii. 静态变量只在第一次使用类时初始化,从第二次使用类时不再进行初始化。

    修饰成员方法:静态方法。

      i. 静态方法不能使用this与super关键字

      ii. 静态方法只能直接调用当前类中静态的成员。想要调用非静态成员必须通过类的对象调用

      iii. 非静态的方法可以直接调用静态的成员。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private String name;
static String num; // 未使用private修饰,可以使用对象调用

静态方法调用成员:
调用静态成员:
Test.num = ""; // 通过类名调用
num = ""; // 直接调用
// this.num = ""; // 错误,static修饰的成员方法(即静态方法)不能使用this与super关键字
new ClassName().num // 通过类的对象调用
调用非静态成员:
// Test.name = ""; // 错误,name不是静态的
// name = ""; // 错误,name不是静态的
// this.name = ""; // 错误,static修饰的成员方法不能使用this与super关键字
new ClassName().name// 只能通过类的对象调用

非静态方法调用成员:
调用静态成员:
Test.num = ""; // 通过类名调用
num = ""; // 直接调用
this.num = ""; // this:当前类的对象引用
new ClassName().num // 通过类的对象调用
调用非静态成员
Test.name = ""; // 错误,只有‘静态成员’才可以用类名(接口名)调用
name = ""; // 直接调用
this.name = ""; // this:当前类的对象引用
new ClassName().name// 通过类的对象调用

静态的特点

​ A:随着类的加载而加载

​ B:优先与对象存在

​ C:被类的所有对象共享

​ D:可以通过类名调用:

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

静态的内存图

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

静态的注意事项

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

​ B:静态只能访问静态

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

​ A:所属不同

​ 静态变量:属于类,类变量

​ 成员变量:属于对象,对象变量,实例变量

​ B:内存位置不同

​ 静态变量:方法区的静态区

​ 成员变量:堆内存

​ C:生命周期不同

​ 静态变量:静态变量是随着类的加载而加载,随着类的消失而消失

​ 成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失

​ D:调用不同

​ 静态变量:可以通过对象名调用,也可以通过类名调用

​ 成员变量:只能通过对象名调用

为什么静态方法中不能使用this与super

static修饰的成员归类所有,this和super代表对象的引用 (有对象才会有引用)。类先于任何实例 (对象) 存在,即 static 修饰的成员在类加载时就已经存在了,但对象在创建时才在内存中生成,所以在静态方法中不能使用 this 与 super 关键字。

对象是类实例化的结果

代码块

1、代码块:在Java中,使用{}括起来的代码被称为代码块。

2、根据其位置和声明的不同,可以分为

    局部代码块:局部位置,用于限定变量的生命周期。

    构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。

      作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。

    静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。

      作用:一般是对类进行初始化。

  思考题?

    静态代码块,构造代码块,构造方法的执行顺序?

      静态代码块 – 构造代码块 – 构造方法

    静态代码块:只执行一次

    构造代码块:每次调用构造方法都执行

demo1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class Test {
private String name;
static String num;

public static void main(String[] args) {
Code a = new Code(); // 创建对象时调用无参构造方法
// Code b = new Code(10); // 创建对象时调用有参的
}
}

/* 结果:
1000
2000
100
200
无参构造方法code
*/
class Code {
// 静态代码块
static {
int a = 1000;
System.out.println(a);
}
// 构造代码块
{
int x = 100;
System.out.println(x);
}
// 构造方法
public Code() {
System.out.println("无参构造方法code");
}
// 构造方法
public Code(int a) {
System.out.println("有参code");
}
// 构造代码块
{
int y = 200;
System.out.println(y);
}
// 静态代码块
static {
int b = 2000;
System.out.println(b);
}
}

demo2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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();
}
}

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

封装

步骤:

  • 类中的成员变量为private(私有)
  • 为私有的成员变量提供公有的get()set()方法。
  • getter和setter方法中加入合法性判断等校验

封装的好处:

  • 隐藏实现细节,提供共有的访问方式

  • 提高了代码的复用性

  • 提高安全性

封装的原则(思想):

  • 将不需要对外提供的内容隐藏起来

  • 把属性隐藏,提供公共方法对其访问

封装的体现:private是封装的一种体现。

总结:

  • 封装是一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。
  • 封装被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
  • 封装特性要求,访问该类的代码和数据,必须通过严格的接口控制。
  • 封装的目的是,在修改代码时只需要修改实现代码片段,而不用修改调用代码片段。
  • 适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

继承(extends)

继承是子类继承父类的特征和行为,能使得

  • 子类对象(实例)具有父类的实例域和方法。
  • 子类从父类继承方法,使得子类具有父类相同的行为。

​ 格式:

    class 子类名 extends 父类名 {}

​ 好处:

    A:提高了代码的复用性

    B:提高了代码的维护性

    C:让类与类之间产生了关系,是多态的前提

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

    开发的原则:低耦合,高内聚。

    耦合:类与类的关系

    内聚:就是自己完成某件事情的能力

img

Java中的继承体系

  • Java中使用extends关键字来表示类继承关系。

  • Java中使用implement关键字来表示接口实现关系。

  • JAVA是(只支持)单继承:一个类只能有一个直接的父类;接口是多实现
    Java支持多层继承(继承体系),儿子继承父亲,父亲继承爷爷。

  • Java也可使用内部类的方式来实现类的多继承特性。

  • 子类可以继承父类所有的成员变量与成员方法(包括private)。
    子类可以继承父类private的成员,但不能使用

  • 子类不能继承父类的构造方法。(可使用super关键字)

  • 若子类和父类中的成员变量或方法名称一样,在子类方法中访问一个变量的查找顺序:
    a:在子类方法的局部范围找,有就使用
    b:在子类的成员范围找,有就使用
    c:在父类的成员范围找,有就使用
    d:如果还找不到,就报错。

  • JAVA中类不能确定自己是否被继承。

  • Java中的继承初始化顺序为: 父类对象属性初始化–>父类对象构造方法–>子类对象属性初始化–>子类对象构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Father {
protected int aaa = 20;
}

class Son extends Father {
private int aaa = 30;
public void show() {
int aaa = 40;
System.out.println(aaa); // 40
System.out.println(this.aaa); // 30
System.out.println(super.aaa); // 20
}
}

访问权限

类(顶层类)只能使用public默认的访问权限修饰。

本类 同包(同包中的类) 子类(不同包中的子类) 其他
private Y
default Y Y
protected Y Y Y
public Y Y Y Y

从上到下:可访问性增强,但封装性变差。

方法的重写(覆盖)

  • 子类根据需要重写父类中的方法。

  • 重写的方法要与被重写的方法具有相同的方法名,参数列表,返回类型。**

  • 重写方法的访问权限要大于等于被重写方法的访问权限。**

  • 重写方法声明的异常必须小于等于被重写方法声明的异常(当父类的方法声明了异常,子类重写的方法可以不声明异常。如果子类重写的方法声明了异常,必须小于等于父类方法声明的异常)。

  • 父类静态方法,子类也必须通过静态方法进行重写。
    static不能产生重写,但现象确实如此,为什么算不上方法重写,因为在多态中这种现象不成立。

  • 父类中私有(private)方法不能产生重写。(可以被“重写”,没有重写的效果,所以并不叫重写)

  • 对于覆写的方法,我们一般使用**@Override**注解标注,有助于静态检查。

super关键字

​ 在子类中引用父类中的成员(通常,在子类中引用父类同名的成员)。

    this和super的用法:

      引用成员:

        this.成员变量 调用本类的成员变量

        super.成员变量 调用父类的成员变量

        this.成员方法 调用本类的成员方法

        super.成员方法 调用父类的成员方法

      引用构造方法:

        this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

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

继承中的构造方法

  a) 子类默认会在自己每一个构造方法的第一行使用super()调用父类无参的构造方法。因为如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化。

​ 子类构造方法执行前默认先执行父类的无参构造方法

  b) 当父类没有无参的构造方法时,而子类也没有调用父类有参数的构造方法,则编译失败。

多态

  • 多态是同一个行为具有多个不同表现形式或形态的能力。
  • 多态就是同一个接口,使用不同的实例而执行不同操作。
  • 同一个事件发生在不同的对象上会产生不同的结果。

格式

父类声明,子类创建。

父 f = new 子();

多态的前提

  A:要有继承关系

  B:要有方法重写。

    其实没有也是可以的,但是如果没有这个就没有意义。

  C:要有父类引用指向子类对象。

多态时只能调用父类的成员

  a) 多态时调用的成员变量一定为父类的成员变量

  b) 多态时调用的成员方法:

    i. 如果子类没有重写此方法,调用的是父类的方法。

    ii. 如果子类重写了父类的方法,调用的是子类的方法

  c) 多态时调用的构造方法:

    创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。

  d) 多态时调用的static方法

    static方法不能产生重写。现象像重写但不是重写,如果子类“重写”static方法,依然调用父类的方法。

img

img

多态的好处/特点:

  • 替换性:父类的引用可替换成任意子类。
  • 扩展性:提高了代码的扩展性(由多态保证),增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。
  • 接口性:父类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
  • 灵活性:在应用中体现灵活多样的操作,提高了使用效率,由继承保证。
  • 简化性:简化对应用软件的代码编写和修改过程,在处理大量对象的运算和操作时尤为重要。

多态的弊端

不能使用子类的特有功能。

我就想使用子类的特有功能?行不行?—————-行。

怎么用呢?

  • 创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)

  • 把父类的引用强制转换为子类的引用。(向下转型)

多态的表现形式

引用多态:

  • 向上转型:父类引用指向子类对象(父类声明,子类创建)
    Fu f = new Zi(); // f是子类型,外界看到的是父类型
  • 向下转型:父类引用转为子类对象
    Zi z = (Zi)f; // 外界看到的是父类型,强转成子类型后,外界看到是子类型。要求该f必须是能够转换为Zi的,也就是说f本身就是Zi,所以才能转。
  • 使用instanceof运算符,判断引用对象的类型,避免类型转换的安全性问题。

img

方法多态:

  • 创建本类对象时,调用本类方法;创建子类对象时,调用为子类重写方法或者继承的方法。
  • 重载 (Overload):一个同名方法可以传入多个参数组合。
  • 覆写 (Override):由于继承关系中的子类有一个和父类同名同参数的方法,会覆盖掉父类的方法。
  • 基本数据类型存在一个方法匹配调用顺序 char -> int -> long -> double,同时也会进行自动装箱,调用包装类方法。

引用数据类型的类型转换

  a) 引用数据类型比较大小:父类大,子类小。

  b) 子类可以直接赋给父类。

  c) 父类必须强转才能赋给子类。

  d) 当父类的引用指向的实例,不是需要的子类类型,则运行时发生异常。

  e) 当两个类没有继承关系时不能相互转换,否则编译失败。

java.lang.Object

  a) 是JAVA中所有类的父类。

  b) toString():当输出一个类的对象时,或将类的对象与字符串连接时。JVM会自动调用类的toString().

  c) ==与equals()

    i. ==:判断栈中的内容是否相等。基本数据类型比较的是值是否相等。引用数据类型比较的是引用是否相等。

    ii. equals():判断当前对象与指定对象是否相等(判断堆中的内容是否相等)。equals()最早出现在Object类中,Object中的equals()仍然判断栈中的内容是否相等。如果自定义的类需要判断是否相等时,建议重写Object类中的equals()方法

抽象类与接口

abstract

  a) 修饰类:抽象类,抽象类不能实例化(不能new),只能使用抽象类的子类进行实例化

        抽象类也有构造方法(抽象类的子类需要在自己构造方法的第一行调用父类的构造方法)。

        那么问题来了:

          抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?

          用于子类访问父类数据的初始化

  b) 修饰方法:抽象方法抽象方法只有方法的声明没有方法的实现子类必须重写父类中所有的抽象方法(当子类为抽象类时,子类可以不重写父类中的抽象方法或只重写父类中部分的抽象方法)。

         抽象方法所在的必须为抽象类。抽象类中不一定有抽象方法。

  c) 修饰接口

  d) abstract不能与哪些关键字一起使用:final,private,static,

      a:final 冲突

      b:private 冲突

      c:static 无意义

  e) 可以使用final关键字定义方法:

    1、修饰类:该类不允许被继承。

    2、修饰方法:方法不能被子类重写。

    3、修饰属性,则该类的该属性不会进行隐式的初始化,构造方法中必须唯一赋值

    4、修饰变量:该变量只能赋一次值,在声明变量的时候才能赋值,即变为常量。

    思考题:final修饰局部变量的问题

        基本类型:基本类型的值不能发生改变。

        引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。

  f) 阻止类被继承有几种方法:1.用final修饰类。2.使用private修饰构造方法。

  总结:

    1). 非抽象类的子类可以为抽象类。

    2). 下面的抽象类可以new

1
2
3
4
5
6
7
8
9
10
11
abstract class Method {
public int sum() {
Method m = new Method() {
public void run() {
}
};
return 0;
}

public abstract void run();
}
  • 如果一个类里面有抽象方法,那么这个类一定是抽象类。
  • 抽象类中抽象方法必须被子类全部实现,如果子类不能全部实现,那么子类必须也是抽象类。

interface

  a) 接口的作用:使JAVA实现多继承

  b) 接口的成员:

    i. 常量:接口中的常量必须为public static final。声明后必须赋值。

    ii. 抽象方法:接口中的方法必须为public abstract的。Java 8 开始有变化: Java 8 默认方法 - 菜鸟Java 5~11 各个版本新特性总结

  c) 类与接口的关系:

    i. 类可以实现(implements)接口。

    ii. 当类实现接口时,类必须重写接口中所有的抽象方法。

    iii. 一个类可以实现多个接口。

  d) 接口不是类,接口中没有构造方法。

  e) 接口不能实例化(不能new)。只能使用接口的实现类 (其实也可以,使用匿名对象时)。

  f) 接口与接口之间的关系:

    i. 接口可以继承接口。

    ii. 一个接口可以继承多个接口。

  • Interface可以使用反射的代理方法,但Abstract Class无法实现反射代理。
  • Interface里面的方法只能声明,不能有具体的实现。(但在Java 8中引入了default关键字,此关键字标注接口方法后,允许接口进行默认实现)。
  • 接口里面的方法也必须全部被子类实现,如果子类不能实现那么子类必须是抽象类。

在实际编程中,建议将继承多用于is-a的关系;将接口看做是has-a关系。抽象类功能较之接口虽多,但扩展性不如接口,优先考虑使用接口来解决问题。

内部类

一个类中嵌套另一个类

  • 内部类可分为静态内部类成员内部类方法内部类匿名内部类
  • 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
  • 内部类的方法可以直接访问外部类的所有成员,包括private
  • 内部类可以帮助实现多继承功能,但不建议使用;提倡使用Interface来实现多继承概念。

类、接口 关系

  A:类与类

    继承关系,只能单继承,可以多层继承

  B:类与接口

    实现关系,可以单实现,也可以多实现。

    还可以在继承一个类的同时,实现多个接口

  C:接口与接口

    继承关系,可以单继承,也可以多继承

抽象类和接口的区别

  A:成员区别

    抽象类:

      成员变量:可以变量,也可以常量

      构造方法:有

      成员方法:可以抽象,也可以非抽象

    接口:

      成员变量:只可以常量

      成员方法:只可以抽象

  B:关系区别:

    类与类:继承,单继承

    类与接口:实现,单实现,多实现

    接口与接口:继承,单继承,多继承

  C:设计理念不同

    抽象类:is a,定义的是共性功能。

    接口: like a,定义的是扩展功能。

形式参数和返回值的问题

形式参数

  类名:需要该类的对象

  抽象类名:需要该类的子类对象

  接口名:需要该接口的实现类对象

案例一:

img

案例二: img

案例三: img

返回值类型

  类名:返回的是该类的对象

  抽象类名:返回的是该类的子类对象

  接口名:返回的是该接口的实现类的对象

案例一: img

案例二: img

案例三: img

链式编程

  对象.方法1().方法2()…….方法n();

  这种用法:其实在方法1()调用完毕后,应该一个对象;

    方法2()调用完毕后,应该返回一个对象。

    方法n()调用完毕后,可能是对象,也可以不是对象。

案例: img

​ 就是文件夹

作用

A:区分同名的类

B:对类进行分类管理

​ a:按照功能分

​ b:按照模块分

举例:

学生:增加,删除,修改,查询

老师:增加,删除,修改,查询

方案1:按照功能分

​ cn.itcast.add

​ AddStudent

​ AddTeacher

​ cn.itcast.delete

​ DeleteStudent

​ DeleteTeacher

​ cn.itcast.update

​ UpdateStudent

​ UpdateTeacher

​ cn.itcast.find

​ FindStudent

​ FindTeacher

方案2:按照模块分

​ cn.itcast.teacher

​ AddTeacher

​ DeleteTeacher

​ UpdateTeacher

​ FindTeacher

​ cn.itcast.student

​ AddStudent

​ DeleteStudent

​ UpdateStudent

​ FindStudent

包的定义

​ package 包名;

​ 多级包用.分开。

注意事项

A:package语句必须在文件中的第一条有效语句

B:在一个java文件中,只能有一个package

C:如果没有package,默认就是无包名

带包的编译和运行

A:手动式

​ a:编写一个带包的java文件。

​ b:通过javac命令编译该java文件。

​ c:手动创建包名。

​ d:把b步骤的class文件放到c步骤的最底层包

​ e:回到和包根目录在同一目录的地方,然后运行带包运行。

B:自动式

​ a:编写一个带包的java文件。

​ b:javac编译的时候带上-d即可

​ javac -d . HelloWorld.java

​ c:回到和包根目录在同一目录的地方,然后运行带包运行。

导包

1、我们多次使用一个带包的类,非常的麻烦,这个时候,Java就提供了一个关键字import。

2、格式:

import包名…类名;

另一种:

import包名…*;(不建议)

3、package,import,class的顺序

package > import > class

Package:只能有一个

import:可以有多个

class:可以有多个,以后建议是一个

常见的修饰符

分类

​ 权限修饰符:private,默认,protected,public

​ 状态修饰符:static,final

​ 抽象修饰符:abstract

常见的修饰组成

类:

​ 权限修饰符:默认修饰符,public

​ 状态修饰符:final

​ 抽象修饰符:abstract

​   常用的:public

成员变量:

​ 权限修饰符:private,默认的,protected,public

​ 状态修饰符:static,final

​   常用的:private

构造方法:

​ 权限修饰符:private,默认的,protected,public

​   常用的:public

成员方法:

​ 权限修饰符:private,默认的,protected,public

​ 状态修饰符:static,final

​ 抽象修饰符:abstract

​   常用的:public

例:

img

另外比较常见的

public static final int X = 10;

public static void show() {}

public final void show() {}

public abstract void show();

内部类

​ 把类定义在另一个类的内部,该类就被称为内部类。

​ 举例:把类B定义在类A中,类B就被称为内部类。

访问规则

  A:可以直接访问外部类的成员,包括私有

  B:外部类要想访问内部类成员,必须创建对象

img

分类

  A:成员内部类:在成员位置定义的类

  B:局部内部类:在局部位置定义的类

img

成员内部类

  A:private 为了数据的安全性

  B:static 为了访问的方便性

  成员内部类不是静态的:

​ 外部类名.内部类名 对象名 = new 外部类名.new 内部类名();

案例1

img

案例2

img

  成员内部类是静态的:

​ 外部类名.内部类名 对象名 = new 外部类名.内部类名();

案例:

img

练习题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// //结果:30,20,10
class Outer {
public int num = 10;

class Inner {
public int num = 20;

public void show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
// System.out.println(new Outer().num); //10
System.out.println(Outer.this.num);
}
}
}

  注意:

    1:内部类和外部类没有继承关系。

    2:通过外部类名限定this对象

      Outer.this

局部内部类

  A:局部内部类访问局部变量必须加final修饰。

  B:为什么呢?

    因为局部变量使用完毕就消失,而堆内存的数据并不会立即消失。

    所以,堆内存还是用该变量,而该变量已经没有了。

    为了让该值还存在,就加final修饰。

    通过反编译工具可以知道,加入final后,堆内存直接存储的是值,而不是变量名。

img

匿名内部类

  A:是局部内部类的简化形式

  B:前提

    存在一个类或者接口

  C:格式:

    new 类名或者接口名() {

      重写方法;

    }

  D:本质:

    其实是继承该类或者实现接口的子类匿名对象

img

匿名内部类在开发中的使用:

  我们在开发的时候,会看到抽象类,或者接口作为参数。

  而这个时候,我们知道实际需要的是一个子类对象。

  如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface Person {
public abstract void study();
}

class PersonDemo {
public void method(Person p) {
p.study();
}
}

class PersonTest {
public static void main(String[] args) {
PersonDemo pd = new PersonDemo();
pd.method(new Person() {
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}

匿名内部类的思考题(补齐代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
interface Inter {
// public abstract void show();
void show();
}

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

面向对象分析题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
分析程序看有没有问题,如果有,说出原因即可。
1.
abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}

2.
public class Something {
void doSomething () {
private String s = "";
int l = s.length();
}
}

3.
abstract class Something {
private abstract String doSomething ();
}

4.
public class Something {
public int addOne(final int x) {
return ++x;
}
}

5.
public class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
o.i++;
}
}
class Other {
public int i;
}

6.
class Something {
int i;
public void doSomething() {
System.out.println("i = " + i);
}
}

7.
class Something {
final int i;
public void doSomething() {
System.out.println("i = " + i);
}
}

8.
public class Something {
public static void main(String[] args) {
Something s = new Something();
System.out.println("s.doSomething() returns " + doSomething());
}
public String doSomething() {
return "Do something ...";
}
}

9.
此处,Something类的文件名叫OtherThing.java
class Something {
private static void main(String[] something_to_do) {
System.out.println("Do something ...");
}
}

10
interface A{
int x = 0;
}
class B{
int x =1;
}
class C extends B implements A {
public void pX(){
System.out.println(x);
}
public static void main(String[] args) {
new C().pX();
}
}

11.
interface Playable {
void play();
}
interface Bounceable {
void play();
}
interface Rollable extends Playable, Bounceable {
Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name = name;
}
public void play() {
ball = new Ball("Football");
System.out.println(ball.getName());
}
}

总结

1:局部变量和成员变量的区别?

  • 在类中位置不同

  • 在内存中位置不同

  • 生命周期不同

  • 初始化值不同

2:形式参数分别为基本类型和引用类型的问题?

形式参数:基本类型 形参的改变不影响实际参数

形式参数:引用类型 形参的改变直接影响实际参数

如果一个方法的形式参数是一个类的名称,那么这里需要的是该类的对象。

3:匿名对象是什么?应用场景是什么?

没有名字的对象。

应用场景:

​ A:调用方法,仅仅调用一次的时候

​ B:作为实际参数传递

4:封装是什么?java中封装的体现有哪些?请举例说明。

封装:隐藏实现细节,提供公共的访问方式。

封装的体现: 类,方法,private修饰成员变量

5:this关键字是什么?this关键字的应用场景?

this:代表当前类的对象应用

应用场景:解决局部变量隐藏成员变量的问题

6:构造方法的作用是什么?构造方法的特点是什么?

构造方法的注意事项是什么?构造方法中可不可以写return语句呢?

作用:用于对对象的数据进行初始化

特点:

   A:方法名和类名相同

   B:没有返回值类型,连void都不能有

   C:没有返回值

注意事项:

   A:如果我们不给构造方法,系统就提供一个默认的无参构造方法

   B:如果我们给出了构造方法,系统就不再提供默认构造方法

      这个时候我们想用,就要自己提供。建议自己提供无参构造方法。

1
2
3
4
5
6
7
   class Student {
      private String name;

      public Student(){}

      //getXxx/setXxx
   }

构造方法可以有return语句,但是不能有明确的返回值。也就是说return;

7:给成员变量赋值有几种方式?

   A:setXxx()

   B:带参构造方法

8:标准的代码编写及测试:

   A:学生类的案例

   B:手机类的案例

   C:长方形类的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   class Student {
      private String name;
      private int age;

      public Student(){}
     
      public String getName() {
         return name;
      }
     
      public void setName(String name) {
         this.name = name;
      }
     
      public int getAge() {
         return age;
      }

      public void setAge(int age) {
         this.age = age;
      }
   }

   class StudentDemo {
      public static void main(String[] args) {
         Student s = new Student();
         s.setName("林青霞");
         s.setAge(27);
         System.out.println(s.getName()+"---"+s.getAge());
      }
   }

9:一个类的成员变量初始化过程

   Student s = new Student();

   A:把Student.class文件加载到内存(类加载器)

   B:在栈内存为s开辟空间

   C:在堆内存为学生对象申请空间

   D:给学生对象的成员变量进行默认初始化

   E:给学生对象的成员变量进行显示初始化

   F:通过构造方法给学生对象的成员变量进行初始化

   G:把堆内存的地址赋值给s变量

10:static关键字是什么?有什么特点?什么时候用呢?

   static静态的意思,可以修饰成员变量和成员方法。

   特点:

      A:随着类的加载而加载

      B:优先与对象存在

      C:被所有对象共享

      D:可以通过类名调用

   什么时候用?

      A:当一个成员被所有对象共享的时候。

      B:工具类的时候。

11:静态变量和成员变量的区别

   A:所属不同

   B:内存位置不同

   C:生命周期不同

   D:调用不同

12:main方法各种修饰符及参数的解释?

   public:权限修饰符,权限最大

   static:可以不用创建对象

   void:返回值给jvm无意义

   main:一个方法名,大家都默认的

   String[] args:接收键盘录入对象

13:Java里关于方法的重写(Override)和重载(Overload),下面说法正确的是 (多选) ABCD

A. 方法重写是指父类与子类之间多态性的一种表现

B. 方法重载是指同一个类中多态性的一种表现

C. 子类中定义的某方法与其父类中的某方法有相同的签名(名称、参数、返回值),称之为方法重写

D. 一个类中定义了多个同名的方法,但方法签名(名称、参数、返回值)不相同,称之为方法重载

14:以下对封装的描述正确的是 D

A. 只能对一个类中的方法进行封装,不能对属性进行封装 

B. 如果子类继承了父类,对于父类中进行封装的方法,子类仍然可以直接调用 

C. 封装的意义不大,因此在编码时尽量不要使用 

D. 封装的主要作用在于对外隐藏内部实现细节,增强程序的安全性

15:下列关于继承的哪项叙述是正确的 D

A. 在java中类允许多继承

B. 在java中一个类只能实现一个接口

C. 在java中一个类不能同时继承一个类和实现一个接口

D. java的单一继承使代码更可靠

回顾1

1:代码块是什么?代码块的分类和各自特点?

2:静态代码块,构造代码块,构造方法的执行流程?

3:继承概述

4:继承的好处

5:Java中继承的特点

6:Java中继承的注意事项?以及我们什么时候使用继承?

7:继承中的成员访问特点

   A:成员变量

      在子类方法中访问一个变量

   B:成员方法

      在测试类中通过子类对象去访问一个方法

8:继承中构造方法的执行流程?假如父类没有无参构造方法,子类应该怎么办?

9:面试题

方法重写和方法重载的区别?方法重载能改变返回值类型吗?

Overload

Override

this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。

10:继承案例练习

11:猜数字小游戏练习。

   通过API学习并使用Math类的random()方法。

回顾2

1:final关键字可以干什么?有什么特点?

   最终的意思。可以修饰类,方法,变量。

   它修饰类,类不能被继承

   它修饰方法,方法不能被重写

   它修饰变量,变量是常量

2:final关键字的面试题?

   A:修饰局部变量

      基本类型:值不能改变

      引用类型:地址值不能改变

   B:初始化时机

      定义的时候

      构造方法中

3:多态是什么,前提是什么?

   同一个对象在不同时刻表现出来的不同的状态

   A:有继承或者实现关系

   B:有方法的重写

   C:有父类或者父接口引用指向子类对象

4:多态中成员访问的特点?

   成员变量

      编译看左边,运行看左边

   成员方法

      编译看左边,运行看右边

   静态方法

      编译看左边,运行看左边

5:多态的好处及弊端?如何解决多态的弊端?

   好处:维护性和扩展性

   弊端:父类不能使用子类特有功能

   如何解决呢?

      A:创建子类对象。(在内存中会多了一个对象)

      B:向下转型

6:什么是向上转型?什么是向下转型?

   子 - 父

   父 - 子

7:多态练习  

   自己做

8:抽象类概述及其特点?

   抽象类:继承的时候,提取了多个方法,而有些方法不是每个子类都是一模一样的实现,

   这个时候,就应该把这样的方法不提供具体实现,而不提供具体实现的方法是一个抽象方法。

         在一个类中,如果有抽象方法,该类必须定义为抽象类。

   特点:

      A:抽象类或者抽象方法由abstract修饰

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

      C:抽象类不能实例化

      D:抽象类的子类

         a:是抽象类

         b:是具体类,就要重写所有抽象方法

9:抽象类成员特点?

   A:成员变量

      有变量,有常量

   B:构造方法

      有。用于子类访问父类数据的初始化

   C:成员方法

      有抽象方法,有非抽象方法

10:抽象类练习?

11:抽象类的小问题

   A:一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?

   B:abstract不能和哪些关键字共存

      final

      static

      private

12:接口的概述及其特点?

   接口:某个继承体系需要扩展功能的时候,就应该实现接口。

   特点:

      A:接口用interface修饰

      B:类实现接口用implements修饰

      C:接口不能实例化

      D:接口的实现

         a:抽象类

         b:具体类,重写接口中的所有抽象方法

13:接口的成员特点?

   A:成员变量 静态常量

   B:成员方法 抽象的

14:抽象类和接口的区别?

   A:成员区别

   B:关系区别

   C:设计理念区别

      “is a”

      “like a”

回顾3

1:形式参数和返回值问题

   形式参数

      基本类型

      引用类型

   返回值类型

      基本类型  

      引用类型

2:包的定义及注意事项

package

第一条有效语句

唯一

3:导包及注意事项

   import

java.lang不需要导入

   java.xxx.yyy.类名; 导入到类的级别

java.xxx.yyy.*; 这个也可以,但是不建议

4:四种权限修饰符及其特点

5:常见的修饰符及组合

   类:public

   成员变量:private

   构造方法:public

   成员方法:public

6:内部类的概述及访问特点

   把类定义在另一个类的内部,叫内部类。

   访问特点:

      内部类可以直接访问外部类的成员,包括私有

      外部类访问内部类的成员需要创建对象

7:内部类的分类

按照位置不同:成员内部类、局部内部类

8:匿名内部类的格式和应用及面试题

1
2
3
4
5
   new 类名或者接口名() {

      重写方法;

   }