慕课网学习Java入门第二季笔记

Java会给成员变量一个初始值,Java不会给局部变量赋予初始值。

静态变量

Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问。当然,鉴于他作用的特殊性更推荐用类名访问。
静态成员属于整个类,当系统第一次使用该类时,就会为其分配内存空间直到该类被卸载才会进行资源回收。

静态方法

与静态变量一样,我们也可以使用 static 修饰方法,称为静态方法或类方法。

  • 静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员。如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问非静态变量。
  • 在普通成员方法中,则可以直接访问同类的非静态变量和静态变量。
  • 静态方法中不能直接调用非静态方法,需要通过对象来访问非静态方法。

静态初始化块

Java 中可以通过初始化块进行数据赋值。如:

public class Main {

    String name;

    {
        name="想念";
    }
}

在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块。如果使用 static 修饰初始化块,就称为静态初始化块。

静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。

public class HelloWorld {
    int num1;
    int num2;
    static int num3;

    public HelloWorld() {
        num1 = 1;
        System.out.println("通过构造方法为变量num1赋值");
    }
    {
        num2 = 2;
        System.out.println("通过初始化块为num2赋值");
    }
    static {
        num3 = 3;
        System.out.println("通过静态初始化块为静态变量num3赋值");
    }
    public static void main(String[] args) {
        HelloWorld hello = new HelloWorld();
        System.out.println("num1:" + hello.num1);
        System.out.println("num2:" + hello.num2);
        System.out.println("num3:" + num3);
        HelloWorld hello2 = new HelloWorld();
    }
}

执行结果:
通过静态初始化块为静态变量num3赋值
通过初始化块为num2赋值
通过构造方法为变量num1赋值
num1:1
num2:2
num3:3
通过初始化块为num2赋值
通过构造方法为变量num1赋值

通过输出结果,我们可以看到,程序运行时静态初始化块最先被执行,然后执行普通初始化块,最后才执行构造方法。由于静态初始化块只在类加载时执行一次,所以当再次创建对象 hello2 时并未执行静态初始化块。

面向对象的三大特性:封装、继承和多态。

内部类

内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。

内部类的主要作用如下:

  1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
  2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据。
  3. 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便。

内部类可分为以下几种:

  • 成员内部类
  • 静态内部类
  • 方法内部类
  • 匿名内部类
成员内部类

内部类中最常见的就是成员内部类,也称为普通内部类。
成员内部类的使用方法:

  1. Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如 public 、 protected 、 private 等。
  2. Inner 类中定义的方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer 类中的私有属性。
  3. 定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( );
  4. 编译程序后,会发现产生了两个 .class 文件,成员内部类的 .class 文件总是这样:外部类名$内部类名.class。
  5. 外部类是不能直接使用内部类的成员和方法。可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。
  6. 如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,可以使用 this 关键字,如:Outer.this.screen。
静态内部类

静态内部类是 static 修饰的内部类,这种内部类的特点是:

  1. 静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问
  2. 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员
  3. 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();
方法内部类

方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用。由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。

多态

  1. 引用多态
    1. 父类的引用可以指向本类的对象
    2. 父类的引用可以指向子类的对象
  2. 方法多态
    1. 创建本类对象时,调用的方法为本类方法
    2. 创建子类对象时,调用的方法为子类重写的方法或者继承的方法
      多态中引用类型转换问题:
package initial;

import child.Dog;
import child.Cat;
import parent.Animal;

/**
 * Created by Administrator on 2017/8/7 0007.
 */
public class Initial {

    public static void main(String[] args) {
        Dog dog = new Dog();
        Animal animal = dog;//向上类型转换 自动类型转换
        Dog dog2 = (Dog)animal;
        Cat cat = (Cat)animal;//1.编译时 Cat类型 2.运行时 Dog类型
    }

}

运行结果:
Exception in thread “main” java.lang.ClassCastException: child.Dog cannot be cast to child.Cat
at initial.Initial.main(Initial.java:16)

通过instanceof运算符避免类型转换的安全性问题,instanceof可以判断一个引用是否是一个类型的子类型。

        if(animal instanceof Cat) {//如果对象含有cat类型的元素,就可以转换
            Cat cat = (Cat)animal;//1.编译时 Cat类型 2.运行时 Dog类型
        }else{
            System.out.println("无法进行转换");
        }

抽象类

抽象类使用abstract关键字修饰,则该类为抽象类。
应用场景:

  • 在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道子类如何实现这些方法。
  • 从多个具有相同特征的类抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性。

abstract定义抽象方法,只有声明,不需要实现,包含抽象方法的类是抽象类。
抽象类中可以有普通的方法,也可以没有抽象方法
抽象类不能直接创建(new),可以定义引用变量指向子类对象

public abstract class Telephone {
    public abstract void call();
    public abstract void message();
}

public class CellPhone extends Telephone {
    @Override
    public void call() {
        System.out.println("通过键盘打电话");
    }

    @Override
    public void message() {
        System.out.println("通过键盘发短信");
    }
}

public class InitialPhone {
    public static void main(String[] args) {
        Telephone  tel1 = new CellPhone();
        tel1.call();
        tel1.message();
        Telephone tel2 = new SmartPhone();
        tel2.call();
        tel2.message();
    }
}

接口

接口可以理解为一种特殊的类,由全部的常量和公共的抽象方法所组成。
类是一种具体实现体,而接口定义了某一批类所需要遵守的规范,接口不关系这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法。

接口就是用来被继承、被实现的,修饰符一般用public。不能使用private和protected修饰接口。

接口可以继承多个父接口

接口中的属性是常量,即使定义时不添加public static final 修饰符,系统也会自动加上。

接口中的方法是抽象方法,即使定义时不添加public abstract 修饰符,系统也会自动加上。

一个类可以实现一个或多个接口,实现接口使用implements。
java中一个类只能继承一个父类,是不够灵活的,通过实现多个接口可以做补充。

例子:
抽象类Telephone
两个子类:CellPhone,SmartPhone
智能手机是可以玩游戏的,可以和PSP相媲美。想要描述游戏机的功能,这时使用抽象类是不合适的。因为传统手机不能打游戏,游戏功能不是手机的共有特征。而且PSP和电话并不是一个类型,不是父子关系。
但是PSP和SmartPhone都具有相同的特征,可以玩游戏。这时就可以用到接口。

接口在使用过程中,还经常与匿名内部类配合使用
匿名内部类就是没有名字的内部类,多用于关注实现而不关注实现类的名称。

package initial;

import child.CellPhone;
import child.Psp;
import child.SmartPhone;
import parent.IPlayGame;
import parent.Telephone;

/**
 * Created by Administrator on 2017/8/8 0008.
 */
public class InitialPhone {
    public static void main(String[] args) {
        Telephone  tel1 = new CellPhone();
        tel1.call();
        tel1.message();
        Telephone tel2 = new SmartPhone();
        tel2.call();
        tel2.message();

        IPlayGame ip1 = new SmartPhone();
        ip1.playGame();
        IPlayGame ip2 = new Psp();
        ip2.playGame();

        IPlayGame ip3 = new IPlayGame() {
            @Override
            public void playGame() {
                System.out.println("使用匿名内部类的方式实现接口");
            }
        };
        ip3.playGame();//通过ip3接口的引用调用父类的方法

        new IPlayGame() {
            public void playGame() {
                System.out.println("使用匿名内部类的方式实现接口2");
            }
        }.playGame();
    }
}

运行结果:
通过键盘打电话
通过键盘发短信
通过语音打电话
通过语音发短信
使用SmartPhone玩游戏
使用PSP玩游戏
使用匿名内部类的方式实现接口
使用匿名内部类的方式实现接口2

UML

Unified Modeling Language统一建模语言,是一个支持模型化和软件系统开发的图形化语言。

用例图(The Use Case Diagram)能够以可视化的方式,表达系统如何满足所收集的业务规则,以及特定的用户需求等信息。
这里写图片描述

序列图(The Sequence Diagram)
序列图用于按照交互发生的一系列顺序,显示对象之间的这些交互。
这里写图片描述

类图(The Class Diagram)
UML类图、业务逻辑和所有支持结构一同被用于定义全部的代码结构。
generalization 泛化
association 关联关系
aggregation 聚合
composition 组合
dependency 依赖关系
realization 实现关系
这里写图片描述

前面打电话功能的类图:
这里写图片描述
在PowerDesigner中选择Language->Generate Java Code还可以生成对应的代码。

Java父类引用指向子类的对象有什么作用?

理解多态,首先要知道“向上转型”。

我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类。我可以通过

Cat c = new Cat();
实例化一个Cat的对象,这个不难理解。但当我这样定义时:

Animal a = new Cat();
这代表什么意思呢?

很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。这就是“向上转型”。

那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特, 定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。 所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,父类引用是无法调用的;


当然有用啦。假如你的A是一个接口,或者抽象类,那么是不可以创建对象的,这样写就可以也能够它的引用去指向他子类或者实现类的对象。这句话写在这里感觉不明显。其实主要是用在方法的参数上,也就是多态性(java的三大特性之一,可想何等重要),为了让你理解深刻,我举个例子。
假如有一个类,这个类需要实现吃各种水果,有香蕉,苹果,梨子等等。
我们是不是就得写:
public void eat(Banana banana) { //…..}
public void eat(Apple apple) { //…..}
等等等等。这样是不是很麻烦啊,但是我要是把这个方法写成:
public void eat(Fruit fruit){//….}
这样只要继承Fruit或者实现Fruit接口,就都可以作为eat的参数,是不是大大简化了编程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值