今日学习两种经典算法冒泡排序和选择排序;静态static和常量final;以及抽象类与接口的知识

1. 冒泡排序:

  • 规则:相邻的两个元素比较,符合条件的换位,每次比较总能得出大的或小的,因此每次循环的次数减一
  • 代码示例:
for (int i = 0; i < nums.length - 1; i++) {
//每轮找出最值,下轮就可以减一个元素比较
            for (int j = 0; j < nums.length - i - 1; j++) {
/* 
   -i:让每次比较的元素减少,即去掉那个上一轮得出的最值(不用比的)
   -1:因为要和后面的元素比较,-1是防止数组元素下标越界
*/
                if (nums[j] > nums[j + 1]) {//从小到大
                    int num = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = num;
                }
            }
        }

2. 选择排序:

  • 规则:用一个元素从头比到尾,就能找到最值,换位后一直比,知道全部排序好(类似穷举法)
  • 代码示例:
for (int i = 0; i < nums.length - 1; i++) {
//比到最后一轮,可以少比一次,因为当比到最后一轮时,它和之前的都比过了,可以减少一次
            for (int j = i + 1; j < nums.length; j++) {
//因为要和后面的每一位比较,之前的比过的不用比,所以起始值为外层循环的数+1
                if (nums[i] > nums[j]) {
                    int tmp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = tmp;
                }
            }
        }

3.static静态关键字

  • static表示“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块。
  • static的效果:被static修饰的成员变量和成员方法独立于该类的任何对象,也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就根据类名在运行时数据区(堆)的方法区内找到他们。也就是说,在这个类被加载时先加载这个类的静态的成员变量和静态成员方法,它的加载是在这个类创建对象之前的,所以static对象可以在它的任何对象创建之前访问,无需引用任何对象。
  • 用法:static修饰后在其它类或方法中,可以用 类名.方法名 或者 类名.属性名直接操作,在本类中可以直接调用。
  • static的好处:使用方便,随时调用,优化方法的复用性。
  • static的缺点:占用静态空间,该空间无垃圾回收机制,除复用性极强的方法,尽量避免使用静态方法。
  • 什么时候使用静态static好:在一个类被实例化为多个对象时,共用一个变量,此时使用静态变量会方便很多。
  • 静态的优先级:静态代码块 > 构造代码块 > 构造方法
    静态代码块:当程序加载到内存时,被执行,全执行一次(只要进入内存就不会再被执行)
    构造代码块:可以给所有对象进行初始化
    构造方法: 给对应的对象进行初始化
    注意:在为创建对象时,静态方法只能调用静态变量;局部变量不能用静态来修饰。

4.变量的种类

  • 类变量:1.由static修饰的变量称为静态变量或类变量。2.用静态修饰,那么该内容被所有对象所共享,此处说的共享,是指所有对象使用同一个变量,而非允许所有人使用,权限是由权限修饰符管理。
  • 成员变量:1.成员变量定义在类中,在整个类中都可以被访问。2.成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中。3.成员变量有默认初始化值。
  • 局部变量:1.局部变量只定义在局部范围内,如:函数内,语句内等,只在所属的区域有效。2.局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。3.局部变量没有默认初始化值。

5.final关键字

  • final关键字可以用来修饰类、方法、变量,各有不同。
  • A:修饰类1.该类不能被继承2.类中方法不会被重写,因此默认都是final的3.用途是:当一个类不需要有子类,不必要被扩展,类实现的细节不允许被改变时,那么就设计成final的
  • B:修饰方法1.这个方法可以被继承,但不能被重写2.用途是:一个类不允许子类重写该方法时,用final修饰3.好处是:可以防止继承他的子类修改该方法的意义和实现;更为高效,编译器在遇到调用final方法转入内嵌机制,提高了执行效率。
  • C:修饰变量1.用final修饰后变为常量,包括静态变量,实例变量和局部变量三种。2.特点:可以先声明,不给初值,这叫做final空白,但是使用前必须赋值一次,并且用final修饰的变量只能赋值一次,一旦被赋值,将不能被改变。
  • D:修饰参数:用final修饰参数时,可以读取该参数,但不能对其做出修改。
  • final关键字不能用来修饰接口和抽象类,但是可以修饰其中的资源。
  • final修饰属性时要注意:final绑定的时属性的值,基本数据类型绑定了数据本身,而引用数据类型绑定的是地址值,即final修饰的引用数据类型,不能更换指向对象实例,但还是可以修改对象实例里面的内容。
final Zi z1=new Zi();
//这样的话要修改z1的类型,修改不了,因为被final绑定了,
//但是可以修改z1对象中的属性。
//因为这样是跳转了两次,第一次跳转到对象,对象的类型被final绑定了,修改不了
//第二次跳转到对象中的属性,这次跳转final绑定不了,所以可以修改其中的属性值

6.抽象类

  • 抽象有什么用:当类里有的方法在描述事务时,不具体,无法准确的描述,这时,我们就可以用抽象来解决这个问题。
  • 抽象的特点:抽象类必须用abstract关键字来修饰:
[访问权限修饰符]    abstract    class    类名{
成员列表
}

抽象方法必须用abstract关键字来修饰,只有方法的的声明,没有方法的实现,没有方法体,并且定义在抽象类中。

[访问权限修饰符]    abstract    返回值类型    方法名(参数列表);
  • 抽象特点总结:
    1.抽象方法没有方法体
    2.抽象方法用abstract修饰
    3.抽象方法只在抽象类中
    4.抽象类,可以没有抽象方法
    5.抽象类中,可以有抽象方法和普通方法
    6.抽象类不能被创建对象,也就是不可以用new创建对象。抽象类通过其子类实例化(创建对象)
    7.子类如果想当一个普通的类必须实现父类的所有抽象方法
    8.子类如果不覆盖(实现)父类的抽象方法,那么子类就是 一个抽象类
  • 抽象方法和普通方法的区别
    1.抽象方法只有方法头,没有方法体。普通方法都有
    2.抽象方法由abstract来修饰,普通方法没有
    3.抽象方法必须活在抽象类中,普通方法既可以活在抽象类中也可以活在非抽象类中
  • 抽象类和普通类的异同
    1.相同点:抽象类和普通类都是用来描述事务的,都在内部定义了成员(方法和属性)。
    2.不同点:普通类有足够信息来描述事务,抽身象类描述事务的信息有可能不够充足;普通类不能定义抽象方法,只能定义普通方法,抽象类中可以定义抽象方法,同时也可以定义普通方法,普通类可以被实例化,抽象类不可以被实例化(创建对象)。
  • 抽象类还要注意的:
    1.抽象类有构造方法,但是接口没有构造方法。
    2.抽象类可以没有抽象方法,abstract不能和private、static、final共存

7.接口

  • 接口的定义:当类中的方法都是抽象时,这个类就叫做接口;接口就是特殊的抽象类,即所有方法都是抽象方法的抽象类就是Java中的接口(interface);接口可以指定一个类必须做什么,而不是规定他如何去做。
  • 接口如何创建
    接口的关键字是:interface
    [访问权限修饰符]    interface    接口名{
    [public]    [static]    [final]    数据类型    变量名=初始化值;
    [public]    [abstract]    返回值    方法();
    接口中只放常量和方法的声明(抽象方法)
  • 接口中要注意的地方:接口中的成员修饰符是固定的,可以省略不写,但也默认是public的;接口中的常量都是静态的,必须赋初值,不能先声明后赋值,只能创建时直接赋初值。
  • 类和接口的关系:类和接口是实现关系,由于接口不能被实例化,所以实现接口的子类必须重写接口中所有的抽象方法,这个子类才能创建对象,否则这个子类就是个抽象类
    图片说明

1.单实现

[访问权限修饰符]    class    类名    implements    接口名{
    重写的接口中的方法(){}
}

2.多实现
Java不支持多继承,但是将多继承机制改良成了多实现;即一个类可以实现多个接口,但要实现多个接口就必须把多个接口中的方法全部实现

[访问权限修饰符]    class    类名    implements    接口名,接口名{
    重写的接口中的方法(){}
}

多实现要实现所有接口的方法,但是多个接口有相同的方法,就只用重写一遍即可

  • 接口和接口之间的关系
    接口和接口之间是继承关系,而且可以多继承,因此接口的出现避免了单继承的局限性
  • 类既可以继承也可以实现:
[访问权限修饰符]    class    类名    extends    类    implements    接口名,接口名{
    重写的接口中的方法(){}
}