【黑马程序员】方法、数组、面向对象、封装、继承——Java复习笔记

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

本章内容较多…

方法

    格式:修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
        方法体语句;
        return 返回值;
    }

    参数分类:
        实参:实际参与运算的数据
        形参:方法上定义的,用于接收实际参数的变量

(1)写方法时首先明确:
    返回值类型:结果的数据类型
    参数列表:参数的个数及对应的数据类型

(2)方法的注意事项
    方法之间是平级关系,不能嵌套定义

(3)方法重载
    在同一个类中,方法名相同,参数的个数、参数的对应数据类型不同。与返回值无关。

数组

(1)数组的初始化
    A:动态初始化
        int[] arr = new int[3];

    B:静态初始化
        int[] arr = new int[]{1,2,3};
        简化版:int[] arr = {1,2,3};

(2)Java的内存分配
    A:栈 存储局部变量(定义在方法内的变量)。数据使用完毕,就消失

    B:堆 存储所有new出来的东西。每一个new出来的东西都有地址。数据使用完毕后变成垃圾,在垃圾回收器空闲的时候回收。

    C:方法区(面向对象部分详细说明)

    D:本地方法区(系统相关)

    E:寄存器(CPU使用)    

    注意:每一个变量都有默认值
        byte,short,int,long 0
        float,double 0.0
        char '\u0000'
        boolean false
        引用类型 null           

(3)数组内存图

    两个栈变量指向同一个堆内存 int[] arr = new int[3];  int[] arr2=arr;可通过arr2修改arr的值,两个数组指向同一个堆内存   

(4)数组操作常见异常
    ArrayIndexOutOfBoundsException 数组越界,访问了不存在的索引
    NullPointerException 空指针,在数组已经不再指向堆内存时继续访问(如:int[] arr ={1,2,3};  arr=null;   sout arr[0];   此时就会抛出空指针异常)

二维数组

(1)格式:
    A:数据类型[][] 数组名 = new 数据类型[m][n];
    B:数据类型[][] 数组名 = new 数据类型[m][];
    C:数据类型[][] 数组名 = new 数据类型[][]{{...},{...},{...}};
    D:数据类型[][] 数组名 = {{…},{...},{...}};

(2)内存分配图:

数组练习题

1.把数组逆序

    public static void arrReverse(int[] arr){
        //操作前一半就行
        for (int i = 0;i<(arr.length)/2;i++){
            //这里运用了b = (a+b)-(a=b); 方式和后半部分对应的数交换位置
            arr[arr.length-(i+1)] = (arr[i]+arr[arr.length-(i+1)])-(arr[i] = arr[arr.length-(i+1)]); 
        }

    }

2.查找指定元素第一次在数组中出现的索引

    public static int arrFind(String abc,String[] arr){

        for (int i=0;i<arr.length;i++){
            if (abc==(arr[i])){
                return i;
            }
        }
        return -1; //若要查找的元素在数组中没有 则返回-1
    }

3.打印杨辉三角形,行数自定义
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
分析:从第2行开始,每行数据=上一行该列数据+上一行前一列数据

    public static void yangHui(int line) {
        if (0 < line && line < 3) {
            System.out.println("最少三行");
        } else if (line <= 0) {
            System.out.println("数据有误");

        } else {
            int[][] yanghui = new int[line][];   //创建二维数组,二维数组里每个元素是每行数据组成的一维数组

            yanghui[0] = new int[]{1};          //录入第一行,第二行数据
            yanghui[1] = new int[]{1, 1};

            System.out.println(1);              //打印第一二行数据
            System.out.println(1 + "\t" + 1);

            for (int x = 2; x < line; x++) {     //开始遍历,从第三行开始
                System.out.print(1 + "\t");        //打印该行第一个数1
                yanghui[x] = new int[x + 1];       //初始化该行数组

                for (int y = 1; y < x; y++) {       //遍历该行数组,从第二列开始 到 倒数第二列
                    yanghui[x][0] = 1;              //添加该行第一列数1和最后一列数1
                    yanghui[x][x] = 1;
                    yanghui[x][y] = yanghui[x - 1][y] + yanghui[x - 1][y - 1];  //计算该行其余列的数据并储存
                    System.out.print(yanghui[x][y] + "\t");

                }

                System.out.println(1);          //打印该行最后一个数1
            }

以上代码较复杂,改进思路:先不打印,只计算、储存数据。最后再用for遍历打印,代码会更整洁易懂

4.加密一个8位整数,加密规则:
首先将数据倒序,然后每位数字+5,再用和除以10的余数代替该数
最后将第一位和最后一位数字交换,打印

获取每个数字的方法:个位 = 12345678 % 10 = 8 ; 十位:12345678/10 % 10 = 7;以此类推

    public static String jiami (int key){
        int[] arr = new int[8];
//      for (int i = 0;i<7;i++){
//          arr[i]=(int)((key/Math.pow(10,(7-i))) % 10);  //将输入的数据前七位放入数组  double强转int
//      }
//      arr[7]=key%10;          //最后一位不用除以10 所以单独放进去
//      arrReverse(arr);            //倒序
        /**
         * 方法改进
         */
        int index = 0,num=key;
        while(num>0){               //因为首先要倒序,所以直接从个位开始录入数组
            arr[index] = num%10;
            index++;
            num/=10;
        }

        for (int i =0;i<index;i++){         //+5求余
            arr[i]=(arr[i]+5)%10;
        }
        arr[0] = arr[0]^arr[index-1];           //交换
        arr[index-1] = arr[0]^arr[index-1];
        arr[0] = arr[0]^arr[index-1];

        String s = "";                      //转换为字符串
        for (int i=0;i<index;i++){
            s += arr[i];
        }
        return s;
    }

5.写一个打印数组方法

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

Java中的参数传递问题

    Java中只有值传递。

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

    例如:main方法里定义了int a=10,b=20两个实参,把a,b传入另一个方法change,change方法里对a,b的值修改,不会影响到main方法里a,b的值,因为ab都是基本数据类型,所以传入参数的时候传递的是值,在change方法里操作数据a=40;b=50;后main方法里ab的数据还是10,20。若传入的是数组等引用数据类型,那么传入的数据实际上是那个地址,所以change方法里改变数据,main方法里的数组也会被改变。

面向对象

(1)面向对象是基于面向过程的编程思想

(2)面向对象的思想特点
    A:是一种更符合我们思考习惯的思想
    B:把复杂的事情简单化
    C:让我们从执行者变成了指挥者

如何让我们的操作更符合面向对象思想呢?
    A:有哪些类
    B:每个类有哪些成员
    C:类与类的关系

(3)类与对象
    A:现实世界的事物
        属性  事物的基本描述
        行为  事物的功能

    B:Java语言中最基本的单位是类。所以,我们要用类来体现事物

    C:类:是一组相关的属性和行为的集合。是一个抽象的概念。
        成员变量    即事物属性
        成员方法    即事物行为

      对象:是该类事物的具体存在,是一个具体的实例。(对象)
  举例:
        学生:类
        班长:对象

(4)类的定义及使用
    类的定义
        成员变量    在类中,方法外
        成员方法    定义格式和以前一样,就是去掉了static。

(5)Java程序的开发,设计和特征
    A:开发:就是不断的创建对象,通过对象调用功能
    B:设计:就是管理和维护对象间的关系
    C:特征:封装,继承,多态

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

(1)在类中的位置不同

(2)在内存中的位置不同
    成员变量:在堆中
    局部变量:在栈中

(3)生命周期不同
    成员变量:随着对象的创建而存在,随着对象的消失而消失
    局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

(4)初始化值不同
    成员变量:有默认值
    局部变量:没有默认值,必须定义,赋值,然后才能使用

(5)局部变量名称可以和成员变量一样,使用时是就近原则

匿名对象

(1)没有名字的对象  new Student();

(2)应用场景
    A:调用方法,仅仅只调用一次的时候。new Student().show();
    b:可以作为实际参数传递。sd.method(new Student());

(3)优点:匿名对象调用完毕就成了垃圾,可以被垃圾回收器回收

封装

(1)隐藏实现细节,提供公共的访问方式,把不想让外界知道的实现细节给隐藏起来,提供公共的访问方式

(2)private是封装的一种体现。

(3)private关键字
特点:被private修饰的后的成员只能在本类中被访问。private方法也只能在本类中调用,不能被外部类调用(需要通过公共方法访问)

this关键字

(1)代表当前类的引用对象
    记住:哪个对象调用方法,该方法内部的this就代表那个对象

(2)应用:
    A:方法的形参与类的成员变量同名时
    B:一个类中的构造器调用同一类中另一个构造器时
            class Person{
                String name; int age;
                public Person(String name){
                    this.name = name; //this.name表示这个对象的name   =号右边的name是构造方法传入的形参
                }
                public Person(String name,int age){
                    this(name); //调用本类其他构造方法
                    this.age = age;
                }
            }

构造方法

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

    思考题:构造方法中可不可以有return语句呢?
        可以。而是我们写成这个样子就OK了:return;
        其实,在任何的void类型的方法的最后你都可以写上:return;

(2)构造方法的注意事项
    A:如果我们没写构造方法,系统将提供一个默认的无参构造方法

    B:如果我们给出了构造方法,系统将不再提供默认构造方法。如果这个时候要使用无参构造方法,就必须自己给出。

(3)给成员变量赋值的方式
    A:setXxx()  
    B:带参构造方法

Student s = new Student();做了哪些事情?

(1)把Student.class文件加载到内存
(2)在栈内存为s开辟空间
(3)在堆内存为学生对象申请空间
(4)给学生的成员变量进行默认初始化。null,0
(5)给学生的成员变量进行显式初始化。林青霞,27
(6)通过构造方法给成员变量进行初始化。刘意,30
(7)对象构造完毕,把地址赋值给s变量         

static关键字

(1)静态的特点:
    A:随着类的加载而加载
    B:优先于对象存在
    C:被类的所有对象共享
    D:可以通过类名调用
        既可以通过对象名调用,也可以通过类名调用,一般用类名调用。

(2)静态的内存
    静态的内容在方法区的静态区

(3)静态的注意事项;
    A:在静态方法中没有this对象。静态变量是随着类的加载而加载,this是随着对象的创建而存在。静态比对象先存在。

    B:静态方法只能访问静态成员变量和静态成员方法

(4)静态变量和成员变量的区别
    A:所属不同
        静态变量:属于类,类变量
        成员变量:属于对象,对象变量,实例变量

    B:内存位置不同
        静态变量:方法区的静态区
        成员变量:堆内存

    C:生命周期不同
        静态变量:静态变量随着类的加载而加载,随着类的消失而消失
        成员变量:成员变量随着对象的创建而存在,随着对象的消失而消失

    D:调用不同
        静态变量:可以通过对象名调用,也可以通过类名调用
        成员变量:只能通过对象名调用

制作、使用帮助文档

(1)写一个类
ps:在同一个文件夹下,类定义在两个文件中和定义在一个文件中是一样的。
把构造方法private后,外界将不能创建对象,只能通过类名调用静态变量和静态方法

(2)加入文档注释
    @param 表示参数

(3)通过javadoc工具生成即可
    javadoc -d 目录 -author -version ArrayTool.java

(4)学习查看API
    java.lang包不需要导入

    查看API步骤:
    先看类的结构
    再看 成员变量:字段摘要。
        构造方法:构造方法摘要。
        成员方法:方法摘要)
    再看构造方法  有or没有、参数列表
    再看成员方法  是否静态、返回值类型、方法名、参数列表

代码块

(1)用{}括起来的代码。

(2)分类:
    A:局部代码块
        用于限定变量的生命周期,及早释放,提高内存利用率。

    B:构造代码块
        在类中的成员位置,把多个构造方法中相同的代码可以放到这里,构造代码块优先于构造方法执行。

        只要调用构造方法,就会优先执行构造代码块
class Code{
    {
        sout10;//sout表示System.out.println();
    }
    public Code( ){
        sout30;
    }
    {
        sout20;
    }
    //输出结果为10 20 30 
}
    C:静态代码块
        在构造代码块前加static。优先于构造代码块执行

        用于对类的数据进行初始化,只执行一次,以后再加载该类,都不执行了。

(3)静态代码块,构造代码块,构造方法的顺序问题?
    静态代码块 > 构造代码块 > 构造方法

(4)综合题,看代码分析结果
public class Test1 {
    static {
        System.out.println("Test1的静态代码块");
    }

    {
        System.out.println("Test1的构造代码块");
    }

    public Test1(){
        System.out.println("Test1的构造方法");
    }

    public static void main(String[] args) {
        System.out.println("我是main方法");
        Zoo.method();
        Zoo s = new Zoo();
        Zoo s2 = new Zoo();
    }
}
class Zoo{

    static void method(){
        System.out.println("Zoo的静态方法");
    }

    public Zoo(){
        System.out.println("Zoo构造方法");
    }

    {
        System.out.println("Zoo构造代码块");
    }

    static {
        System.out.println("Zoo静态代码块");
    }
}
输出结果为
Test1的静态代码块
我是main方法
Zoo静态代码块
Zoo的静态方法
Zoo构造代码块
Zoo构造方法
Zoo构造代码块
Zoo构造方法

若将main方法内容改为如下:
System.out.println("我是main方法");
Zoo s = new Zoo();
s.method();
Zoo s2 = new Zoo();
则输出结果为
Test1的静态代码块
我是main方法
Zoo静态代码块
Zoo构造代码块
Zoo构造方法
Zoo的静态方法
Zoo构造代码块
Zoo构造方法

继承

(1)继承的好处:
    A:提高了代码的复用性
    B:提高了代码的维护性
    C:让类与类产生了一个关系,是多态的前提

(2)继承的弊端:
    A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。

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

    B:打破了封装性

(3)Java中继承的特点
    A:Java中类只支持单继承
    B:Java中可以多层(重)继承(继承体系)

(4)继承的注意事项:
    A:子类不能继承父类的私有成员

    B:子类不能继承父类的构造方法,但是可以通过super去访问

    C:不要为了部分功能而去继承

(5)什么时候使用继承呢?
    采用假设法,A是B的一种,或者B是A的一种,则可以用继承

(6)super关键字
    用于访问父类

    比如子类成员变量、父类成员变量和子类方法内部都定义了num,子类方法若访问方法内部的num就直接调用,访问子类的num要用this,访问父类的num就用super       

(7)Java继承中的成员关系
    A:成员变量
        子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢?
            子类的方法访问变量的查找顺序:
                在子类方法的局部范围找,有就使用。
                在子类的成员范围找,有就使用。
                在父类的成员范围找,有就使用。
                找不到,就报错。

    B:构造方法
        a:子类中所有构造方法都会默认会去访问父类的无参构造方法,并且先执行父类的构造方法,再执行子类的构造方法

            why?because子类初始化前必须要先把父类初始化
            子类每一个构造方法的第一条语句都默认为super();  是Java自动加上的

        b:父类中如果没有无参构造方法,怎么办?
            要么在子类构造方法中通过super去明确调用父类带参构造,注意,super(…);必须是该方法第一条语句。若不是第一条,就可能对父类的数据进行多次初始化,所以必须第一条;

            要么子类通过this(...);调用本身的其他构造方法,但是被调用的这个构造方法必须有用super调用父类带参构造。即子类中至少要有一个构造方法去访问父类的构造方法;

            要么在父类中加一个无参构造。

    C:成员方法
        子类的成员方法和父类中的成员方法名称一样,这个怎么访问呢?
            通过子类对象访问一个方法的查找顺序:
                在子类中找,有就使用
                在父类中找,有就使用
                找不到,就报错

(8)两个面试题:
    A:Override和Overload的区别?Overload是否可以改变返回值类型?
        重写要求子类方法同父类方法声明完全一样(参数列表、返回值类型、方法名、是否静态)。

        重写后若需要调用被重写的父类方法,则加上super.方法名(..);即可实现子类继承父类方法后增加新的功能

            注意:A.父类中的私有方法不能被重写,因为根本都无法继承
                 B.重写方法的访问权限不得低于被重写方法的访问权限  public大于默认(不写访问修饰符)

        重载要求参数列表不一样,方法名一样,返回值类型无所谓

    B:this和super的区别和各自的作用?
        this代表本类对象的引用。super代表父类存储空间的标识(可以理解为父类引用,可以操作父类成员)  

用法区别
        A:访问成员变量  this.成员变量    super.成员变量
        B:访问构造方法  this(..)       super(..)
        C:访问成员方法  this.成员方法()  super.成员方法()

例题:

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

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

class Y{
    Y(){
        System.out.print("y");
    }
}
打印结果为yxyz

原因:
初始化步骤是先父后子(分层初始化),先默认初始化,后显式初始化(即成员变量int a = 10;直接初始化),最后构造方法初始化

super()在子类构造方法中只代表先初始化父类

分析过程:
创建Z对象,Z继承自X,所以需先访问X构造方法,所以先初始化X类,于是执行X类里的Y b = new Y();所以最先创建Y对象并打印出y。然后执行X构造方法打印x。然后回到Z类初始化,先Y y = new Y();于是又打印y,然后执行z构造方法打印z
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值