No_16_0229 Java基础学习第八天

文档版本 开发工具 测试平台 工程名字 日期 作者 备注
V1.0 2016.02.29 lutianfei none

[TOC]


工具类中使用静态方法

  • 当报错无法从静态上下文中引用非静态 方法xxx

    • 表明在静态方法中引用了非静态方法
  • 在工具类中当把构造方法私有后,外界就不能再创建对象了,此时将所有方法设为静态后。可以根据静态方法的特点:通过类名来调用

  • Eg:

/*
    我想要对数组进行操作
    在同一个文件夹下,类定义在两个文件中和定义在一个文件中其实一样的。
*/
class ArrayDemo {
    public static void main(String[] args) {
        //定义数组
        int[] arr = {28,55,37,46,19};

        //静态方法
        //printArray(arr);
        
        //非静态方法
        //ArrayDemo ad = new ArrayDemo();
        //ad.printArray(arr);

        //方法改进为静态后,就可以直接通过类名调用
        ArrayTool.printArray(arr);
    }
}


class ArrayTool {
    
    //把构造方法私有,外界就不能在创建对象了
    private ArrayTool(){}

    public static void printArray(int[] arr) {
        for(int x=0; x<arr.length; x++) {
            if(x == arr.length-1) {
                System.out.println(arr[x]);
            }else {
                System.out.print(arr[x]+", ");
            }
        }
    }
}

帮助文档的制作

  • 制作工具类

    • ArrayTools
  • 制作帮助文档(API)

    • javadoc -d 目录 -author -version ArrayTool.java
      • 目录可以写一个文件的路径
  • 制作帮助文档出错:

  • 找不到可以文档化的公共或受保护的类:告诉我们类的权限不够。修改方法在类前面加public修饰。

如何使用帮助文档

  • 点击显示,找到索引,出现输入框
  • 你应该知道你找谁?举例:Scanner
  • 看这个类的结构(需不需要导包) 注:java.lang包下的类不需要导入,其他的全部需要导入。
    • 成员变量 说明书中对照为字段摘要
    • 构造方法 说明书中对照为构造方法摘要
      • 有构造方法 : 创建对象
      • 没有构造方法:成员可能都是静态的,通过类名调用。
    • 成员方法 方法摘要
      • 看左边
        • 是否静态:如果静态,可以通过类名调用
        • 返回值类型:定义返回的是说明,就用什么接收。
      • 看右边
        • 方法名,不要打错
        • 参数列表:需要什么参数,就给什么,需要几个给几个
    • 看版本说明
  • 看这个类的说明
    • 看构造方法
    • 看成员方法

Math类学习

/*
    Math:类包含用于执行基本数学运算的方法
    
    由于Math类在java.lang包下,所以不需要导包。
    特点:
        没有构造方法,因为它的成员全部是静态的。
        
    掌握一个方法:
        获取随机数
        public static double random():返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。
*/
class MathDemo {
    public static void main(String[] args) {
        //获取一个随机数
        //double d = Math.random();
        //System.out.println(d);
        
        //需求:我要获取一个1-100之间的随机数,肿么办?
        for(int x=0; x<100; x++) {
            int number = (int)(Math.random()*100)+1;
            System.out.println(number);
        }
    }
}

代码块

  • 在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为局部代码块构造代码块静态代码块同步代码块(多线程讲解)。

  • 局部代码块

    • 方法中出现;限定变量生命周期,及早释放,提高内存利用率
  • 构造代码块

    • 类中,方法外出现;
    • 多个构造方法中相同的代码存放到一起,每次调用构造都执行,并且在<font color = red>构造方法</font>执行。
      • 作用:可以把多个构造方法中的共同代码放到一起。
  • 静态代码块

    • 类中,方法外出现,加了static修饰;用于给类进行初始化,在加载的时候就执行,并且<font color = red>只执行一次</font>。
  • eg1 :

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);
    }
}

class CodeDemo {
    public static void main(String[] args) {
        //局部代码块
        {
            int x = 10;
            System.out.println(x);
        }
        //找不到符号
        //System.out.println(x);
        {
            int y = 20;
            System.out.println(y);
        }
        System.out.println("---------------");
        
        Code c = new Code();    
        System.out.println("---------------");
        Code c2 = new Code();
        System.out.println("---------------");
        Code c3 = new Code(1);
    }
}


/*
* 程序运行结果:
10
20
---------------
1000
2000
100
200
code
---------------
100
200
code
---------------
100
200
code
*/


  • Eg2 :
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();
    }
}

/*
    写程序的执行结果。
    
    林青霞都60了,我很伤心
    我是main方法
    Student 静态代码块
    Student 构造代码块
    Student 构造方法
    Student 构造代码块
    Student 构造方法
*/


继承

继承概述

  • 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
  • 通过extends关键字可以实现类与类的继承
    • class 子类名 extends 父类名 {}
  • 单独的这个类称为父类基类或者超类;这多个类可以称为子类或者派生类
  • 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
class Dad(){}
class Son extends Dad {}


继承的好处

  • 提高了代码的复用性

    • 多个类相同的成员可以放到同一个类中
  • 提高了代码的维护性

    • 如果功能的代码需要修改,修改一处即可
  • 让类与类之间产生了关系,是多态的前提

    • 其实这也是继承的一个弊端:类的耦合性很强
  • 开发的原则:低耦合,高内聚

    • 耦合:类与类的关系。
    • 内聚:就是自己完成某件事情的能力。

Java中继承的特点

  • Java只支持单继承,不支持多继承。
    • 一个类只能有一个父类,不可以有多个父类。
      • class SubDemo extends Demo{} //ok
      • class SubDemo extends Demo1,Demo2...//error
  • Java支持多层继承(继承体系)
    • class A{}
    • class B extends A{}
    • class C extends B{}

Java中继承的注意事项

  • 子类只能继承父类所有非私有的成员(成员方法和成员变量)
    • 其实这也体现了继承的另一个弊端:打破了封装性
  • 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
  • 不要为了部分功能而去继承
  • Eg1:
class Father {
    private int num = 10;
    public int num2 = 20;
    
    //私有方法,子类不能继承
    private void method() {
        System.out.println(num);
        System.out.println(num2);
    }
    
    public void show() {
        System.out.println(num);
        System.out.println(num2);
    }
}

class Son extends Father {
    public void function() {
        //num可以在Father中访问private
        //System.out.println(num); //子类不能继承父类的私有成员变量
        System.out.println(num2);
    }
}

class ExtendsDemo3 {
    public static void main(String[] args) {
        // 创建对象
        Son s = new Son();
        //s.method(); //子类不能继承父类的私有成员方法
        s.show();
        s.function();
    }
}


什么时候使用继承呢?

  • 继承中类之间体现的是:”is a”的关系。
  • 假设法:如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。

继承中成员变量的关系

  • 案例演示
    • 子父类中同名和不同名的成员变量
  • 结论:
    • 在子类方法中访问一个变量
    • 首先在子类局部范围找
    • 然后在子类成员范围找
    • 最后在父类成员范围找(肯定不能访问到父类局部范围)
    • 如果还是没有就报错。(不考虑父亲的父亲…)
super关键字
  • super的用法和this很像
    • this代表本类对应的引用。
    • super代表父类存储空间的标识(可以理解为父类引用)
  • 用法(this和super均可如下使用)
    • 访问成员变量
      • this.成员变量
      • super.成员变量
    • 访问构造方法(子父类的构造方法问题讲)
      • this(…) :调用本类构造方法
      • super(…):调用父类构造方法
    • 访问成员方法(子父类的成员方法问题讲)
      • this.成员方法()
      • super.成员方法()

继承中构造方法的关系

  • 子类中所有的构造方法默认都会访问父类中的<font color =red>无参</font>构造方法
    • 因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化
    • 每一个构造方法的第一条语句默认都是:super()
class Father {
    int age;

    public Father() {
        System.out.println("Father的无参构造方法");
    }
    
    public Father(String name) {
        System.out.println("Father的带参构造方法");
    }
}

class Son extends Father {
    public Son() {
        //super();//默认都会有的
        System.out.println("Son的无参构造方法");
    }
    
    public Son(String name) {
        //super();//默认都会有的
        System.out.println("Son的带参构造方法");
    }
}    

class ExtendsDemo6 {
    public static void main(String[] args) {
        //创建对象
        Son s = new Son();
        System.out.println("------------");
        Son s2 = new Son("林青霞");
    }
}
  • 程序运行结果:



  • 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢,如何解决?
    • 会报错
    • 解决办法:
      • A:在父类中加一个无参构造方法
      • B:通过使用super关键字去显示的调用父类的带参构造方法
    • 子类中一定要有一个方法访问了父类的构造方法,否则父类数据就没有办法初始化。
  • 注:super(...)必须放在第一条语句上,否则就可能出现对父类的数据进行了多次初始化,所以必须放在第一条语句上面。
  • 一个类的初始化过程
    • 成员变量进行初始化
    • 默认初始化
    • 显示初始化
    • 构造方法初始化

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


  • 练习1
/*
    看程序写结果:
        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();
    }
}
  • 练习2:
/*
    看程序写结果:
        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();
    }
}


  • 练习3(<font color = red>有难度理解不深刻</font>)
/*
    看程序写结果:
        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(); 
    }
}


继承中成员方法的关系

方法重写概述

  • 子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖方法复写
  • 使用特点:
    • 如果方法名不同,就调用对应的方法
    • 如果方法名相同,最终使用的是子类自己的
  • 方法重写的应用:
    • 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。

方法重写的注意事项

  • 父类中私有方法不能被重写
  • 子类重写父类方法时,访问权限不能更低
  • 父类静态方法,子类也必须通过静态方法进行重写。(其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中会讲解)
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("林青霞");
    }
}

练习题

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

    • 方法重写(Override)
      • 在子类中,出现和父类中一模一样的方法声明的现象。
    • 方法重载(Overload)
      • 同一个类中,出现的方法名相同,参数列表不同的现象。
    • 方法重载能改变返回值类型,因为它和返回值类型无关。
  • Eg2: this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。

    • this:代表当前类的对象引用
    • super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)
    • 场景:
      • 成员变量:
        • this.成员变量
        • super.成员变量
      • 构造方法:
        • this(...)
        • super(...)
      • 成员方法:
        • this.成员方法
        • super.成员方法
  • Eg3:

//定义人类
class Person {
    //姓名
    private String name;
    //年龄
    private int age;
    
    public Person() {
    }

    public Person(String name,int age) { //"林青霞",27
        this.name = name;
        this.age = age;
    }
    
    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 Student extends Person {
    public Student() {}
    
    public Student(String name,int age) { //"林青霞",27
        //this.name = name;
        //this.age = age;
        super(name,age);
    }
}

//定义老师类
class Teacher extends Person {

}

class ExtendsTest4 {
    public static void main(String[] args) {
        //创建学生对象并测试
        //方式1
        Student s1 = new Student();
        s1.setName("林青霞");
        s1.setAge(27);
        System.out.println(s1.getName()+"---"+s1.getAge());
        
        //方式2
        Student s2 = new Student("林青霞",27);
        System.out.println(s2.getName()+"---"+s2.getAge());
        
        //补齐老师类中的代码并进行测试。
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容