• 狂神说 JavaSE入门笔记(三)


    7 数组

    7.1 数组概述

    数组是相同类型数据的有序集合

    可以通过下标来访问,下标从0开始

    7.2 数组创建

    声明创建

    首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:

    dataType[] arrayRefVar; // 首选的方法

    dataType arrayRefVar[]; // 效果相同,但不是首选方法

    Java语言使用new操作符来创建数组,语法如下:

    arrayRefVar = new dataType[arraySize];

    上面的语法语句做了两件事:

    1. 使用 dataType[arraySize] 创建了一个数组。
    2. 把新创建的数组的引用赋值给变量 arrayRefVar。

    当然也可以使用一行代码完成声明和创建:

    int[] numbers = new int[100];
    

    可以通过numbers.length获取长度

    初始化

    有三种初始化

    • 静态初始化:

      int[] numbers = {1,2,3};
      Person[] people = {new Person(),new Person()};
      
    • 动态初始化:包含默认初始化

      int[] numbers = new int[10];
      b[0] = 1;
      
    • 默认初始化:数组是引用类型,其中的元素相当于类的实例变量,因此数组一经分配空间,其中的元素就按照实例变量同样的方式被隐式初始化。

    内存分析

    Java内存分为:

    • 堆:存放new的对象和数组
    • 栈:存放基本变量类型,包括具体数值。存放引用对象的变量,包括具体地址。
    • 方法区:包含所有class和static变量,方法区是特殊的堆。

    声明数组时,数组并不存在,只是在栈中压入一个变量

    创建数组时,数组才会存在,在堆中真正地开辟出空间

    下标越界

    访问下标超出数组大小会产生下标越界异常。

    基本特点

    • 长度确定
    • 相同类型
    • 元素可以是任意的类型
    • 数组是引用类型,数组可以看成是对象,Java中的对象保存在堆中,无论数组对象中存什么数据类型,数组所占空间是在堆中的,返回的引用是在栈里的。引用:栈--->堆

    7.3 数组使用

    • 使用for循环
    • 使用for-each循环即增强型for
    • 使用数组作为方法的参数
    • 使用数组作为返回值

    7.4 多维数组

    数组的元素还是数组

    int[][] nums = new int[2][5];
    int[][] numbers = {{1,2},{3,4},{5,6}};
    

    7.5 Arrays类

    数组的工具类java.util.Arrays

    Arrays类中的方法都是static修饰的静态方法,可以直接使用类名调用

    有以下常用功能

    • 给数组赋值:通过 fill 方法。
    • 对数组排序:通过 sort 方法,按升序。
    • 比较数组:通过 equals 方法比较数组中元素值是否相等。
    • 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。

    7.6 冒泡排序

    public static void sort(int[] array){
    	for(int i=0;i<array.length-1;i++){
            
            boolean flag = false;//优化,跳过没有意义的比较轮次
            
            //减i是因为进行i次比较后,产生了i个最大或最小的数不需要进行下次比较
            for(int j=0;j<array.length-1-i;j++){
                if(array[j+1]<array[j])
                    swap(array[j+1],array[j]);
            }
            if(flag == flase)
                break;
        }
    }
    

    7.7 稀疏数组

    数组中大部分为0,或其他相同元素时,采用的一种压缩存储方式。

    即只记录数组行列等基本信息,以及有效信息

    8 面向对象

    8.1 初识面向对象

    面向过程

    面向对象

    以类的方式组织代码,以对象的方式封装数据

    8.2 方法

    回顾:如何定义方法

    静态方法:可以通过类名调用

    非静态方法:需要实例化对象,借用对象调用

    形参实参

    值传递引用传递

    this关键字:用来表示当前对象本身,或当前类的一个实例,通过 this 可以调用本对象的所有方法和属性。

    8.3 对象创建分析

    使用new创建对象,创建时会

    • 分配内存空间
    • 默认初始化
    • 调用构造方法

    构造方法

    • 方法名和类名相同
    • 没有返回类型,不能写成void

    一旦定义了有参构造,无参构造就必须显式定义

    new本质是在调用构造器

    内存分析

    内存分析

    8.4 三大特性

    封装

    高内聚,低耦合

    • 模块内部联系紧密
    • 模块之间联系松散

    封装:数据的隐藏,将数据封装起来,只暴露给外界接口

    属性:private

    方法:getter/setter

    封装的优点:

    • 良好的封装能够减少耦合。
    • 类内部的结构可以自由修改。
    • 可以对成员变量进行更精确的控制。
    • 隐藏信息,实现细节。

    继承

    继承是类于类之间的关系,除此之外类与类之间的关系还有依赖,组合,聚合。继承:is a关系

    Java只有单继承

    控制访问与继承的规则

    • 父类中声明为 public 的方法在子类中也必须为 public。
    • 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
    • 父类中声明为 private 的方法,不能够被继承。

    Object类

    在Java中,所有的类都继承了Object类

    super关键字:表示当前类的父类

    • super调用父类的构造方法,必须在父类方法的第一个
    • super只能出现在子类方法或者是构造方法中
    • super和this不能同时调用构造方法

    一般在写了带参数构造器后,都需要显式写出无参构造器

    方法重写

    重写是方法的重写与属性无关

    静态方法:方法调用只和定义时的类有关,其实是通过类名在调用

    非静态方法:重写,用实例化对象调用

    父类

    public class A {
        public static void test_static(){
            System.out.println("A=>test_static");
        }
    
        public void test(){
            System.out.println("A=>test");
        }
    }
    

    子类

    public class B extends A{
        public static void test_static(){
            System.out.println("B=>test_static");
        }
    
        @Override
        public void test(){
            System.out.println("B=>test");
        }
    }
    

    测试

    public class test {
        public static void main(String[] args) {
    
            B b = new B();
            A a= new B();
    
            b.test_static();
            a.test_static();
    
            a.test();
            b.test();
        }
    }
    

    输出

    B=>test_static
    A=>test_static
    B=>test
    B=>test
    

    总结

    • 重写需要有继承关系,子类重写父类的关系
    • 方法名相同
    • 参数列表相同
    • 修饰符:范围可以扩大但不能缩小
      • 父类是protected子类改为public
    • 异常:可以缩小但不能扩大
      • 父类是Exception子类是ClassNotFoundException

    不能重写的方法

    • static方法属于类,不属于实例
    • final修饰的方法
    • private 私有的方法无法重写

    不能继承的类

    • 被final修饰的类

    多态

    动态编译:类型在执行时才能确定

    同一方法可以根据发送对象的不同而采用多种不同的行为方式

    一个对象的实际类型是确定的

    但可以指向的引用类型就不一定了,父类引用可以指向子类的对象

    父类

    public class Person {
        public void run(){
            System.out.println("run");
        }
    }
    

    子类

    public class Student extends Person{
        public void eat(){
            System.out.println("eat");
        }
    
        @Override
        public void run() {
            System.out.println("sonRun");;
        }
    }
    

    测试

    public class Test {
        public static void main(String[] args) {
    
            Student s1 = new Student();
            Person s2 = new Student();
    
            s1.run();//两个类型都有run方法且子类重写,执行子类的
            s2.run();
    
            s1.eat();//eat方法是子类独有的,父类无法调用
            //s2.eat();//报错
        }
    }
    

    输出

    sonRun
    sonRun
    eat
    

    总结:

    多态是方法的多态,属性没有多态

    多态存在条件:

    1. 有继承关系
    2. 子类重写父类的方法
    3. 父类引用指向子类对象

    多态的实现可以有以下几种:

    1. 重写
    2. 接口
    3. 抽象类和抽象方法

    8.5 instanceof

    判断一个类型是不是某种类型

    A instanceof B

    看A和B有没有继承关系,

    同级别类是无法通过编译的

    8.6 类型转换

    引用类型转换

    同样的高转低要强制转换

    低转高是直接实现可以的

    如果子类转为父类就可能会丢失一些子类自己本来的方法

    子类转父类 向上转型

    父类转子类 向下转型 强制转换

    8.7 static

    static变量

    static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本【存放在方法区】,它当且仅当在类初次加载时会被初始化【加final和不加final的static变量初始化的位置不一样】。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

    static方法

    static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

    static静态代码块

    static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次【根据class加载原理 每个类加载一次 使用双亲委托加载】。

    初始化的顺序 静态代码块 > 构造代码块 > 构造函数

    测试

    public class Test {
        {
            System.out.println("匿名代码块");
        }
    
        static{
            System.out.println("静态代码块");
        }
    
        public Test(){
            System.out.println("构造方法");
        }
    
        public static void main(String[] args) {
            Test test = new Test();
            System.out.println("=========");
            Test test2 = new Test();
        }
    }
    

    执行

    静态代码块
    匿名代码块
    构造方法
    =========
    匿名代码块
    构造方法
    

    static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次,之后会按匿名代码块,构造方法的顺序执行

    很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

    静态内部类

    ​ pass

    静态导包

    import static java.lang.Math.random;//下面使用时可以直接调用random()
    

    8.8 抽象类

    abstract修饰符可以修饰方法也可以修饰类,abstract修饰方法就是抽象方法,abstract修饰类就是抽象类。

    抽象类中可以没有抽象方法,但是一旦定义的抽象方法就必须声明为抽象类。抽象类也可以写普通方法。

    抽象类:不能实例化,不能new,它就是用来让别人继承的

    抽象方法:只有方法的声明,没有实现,子类需要实现。

    子类继承抽象类就需要实现抽象方法,否则它也应当声明为抽象类


    但是抽象类本质还是一个类,别人需要用extends继承,但是Java只有单继承

    这是需要引入接口,接口可以实现多继承

    思考:抽象类也存在构造器

    8.9 接口

    接口:只有规范。可以实现约束和实现分离--->面向接口编程

    接口就是规范,定义的是一组规则。体现的是现实世界中“如果你是...则必须能...”的思想

    接口的本质是契约,像法律,制定好了大家都要遵守

    面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。

    设计模式其实就是在研究:如何合理地去抽象


    接口中定义方法都是抽象的,而且默认是public abstract,可以不写

    接口中定义的属性都是常量,默认public static final,一般没人在接口里定义属性

    使用接口时要注意锻炼自己的抽象思维能力

    总结

    1. 接口是约束
    2. 接口定义一些方法,让不同的人实现
    3. 接口方法默认是public abstract
    4. 接口属性默认是public static final
    5. 接口不能被实例化,接口也没有构造方法
    6. implements可以实现多个接口

    8.10 内部类

    内部类就是在类的内部再定义一个类

    一个java类可以有多个class,但只能有一个public class

    • 成员内部类

    • 静态内部类

    • 局部内部类

    • 匿名内部类

    9 异常

    什么是异常

    程序运行时出现的不期而至的情况,文件找不到,网络链接失败等

    要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:

    • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
    • 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
    • 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

    异常体系结构

    所有的异常类是从 java.lang.Exception 类继承的子类。

    Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。

    Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。

    Error 用来指示运行时环境发生的错误。

    例如,JVM 内存溢出。一般地,程序不会从错误中恢复。

    异常类有两个主要的子类:IOException 类和 RuntimeException 类。

    graph TD A(Throwable) -->B(Exception) A -->C(Error) B -->D(IOException) B -->E(RuntimeException)

    Error

    Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者执行的操作无关。

    Error是灾难性的致命的错误,是程序无法控制和处理的

    Exception

    Exception通常是可以被程序处理的。我们应当尽量避免一些异常的产生。

    捕获和抛出异常

    抛出异常

    捕获异常

    五个关键字

    try,catch,finally,throw,throws

    主动抛出异常

    一般在方法中使用。

    if(b == 0){
    	throw new ArithmeticException();
    }
    

    在方法上抛出异常throws

    public void method(int a,int b) throws IOException{
        }
    

    自定义异常

    在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。

    • 所有异常都必须是 Throwable 的子类。
    • 如果希望写一个检查性异常类,则需要继承 Exception 类。
    • 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。

    可以像下面这样定义自己的异常类:

    class MyException extends Exception{
        }
    

    实例

    public class MyException extends Exception
    {
      private int number;
      public MyException(int number)
      {
        this.number = number;
      } 
      @Override
      public String toString(){
      	return "MyException: "+number;
      }
    }
    
  • 相关阅读:
    bat入门--第一个bat文件
    Egret的Shape
    Less Time, More profit 最大权闭合子图(最大流最小割)
    Mayor's posters POJ
    Stars POJ
    Snacks
    有趣的数列 卡特兰数
    Devu and Flowers lucas定理+容斥原理
    整数分解为2的幂 数学
    易碎的鸟蛋 概率DP
  • 原文地址:https://www.cnblogs.com/programthinking/p/13827573.html
Copyright © 2020-2023  润新知