Java基础知识点总结笔记

Java基础

Java常用内存区域

  1. 栈内存空间:存储引用堆内存空间的地址
  2. 堆内存空间:保存每个对象的具体属性内容
  3. 全局数据区:保存static类型的属性
  4. 全局代码区:保存所有的方法定义

创建对象的过程

创建对象的过程:

  1. 遇到对象名时,进行类的加载(只加载一次)
  2. 创建对象,为这个对象在堆中开辟空间
  3. 为对象进行属性的初始化操作

JavaBean

JavaBean是Java写成的可重用组件

符合以下标准的Java类:称之为JavaBean:

  1. 类是公共的
  2. 有一个无参的公共的构造器
  3. 有属性,且有对应的get、set方法

修饰符

权限修饰符

修饰符 同一个类中 同一个包中子类无关类 不同包的子类 不同包的无关类
private
默认
protected
public

状态修饰符

static关键字

  1. 声明属性:使之独立于对象,成为全局属性(亦称静态属性)
  2. 声明方法:使之成为"类方法",可直接通过类名调用:<类名>.<方法名>()
  3. 静态成员方法只能访问静态的成员变量或方法

final关键字

  1. final声明的类不能有子类
  2. final声明的方法不能被子类覆写
  3. final修饰的变量
    1. 基本类型:修饰数据值,不能被改变
    2. 引用类型:修饰地址值,地址不可以被改变,地址指向的数据可以改变

其他关键字

this关键字

  1. 表示该类的属性变量:this.变量名

  2. 调用本类的构造方法:this()

  3. 表示当前类,可调用成员方法:this.成原方法名()

new关键字

调用类的构造器(构造方法)

关于构造器

  1. 调用构造器时,若未写空构造器,系统会默认分配一个空构造器。
  2. 构造器的重载
    1. 重载一般要保证写好空构造器:若未写,系统不会默认分配,调用就会报错
    2. 构造器重载便于为属性赋值(可因对象不同值不同)
  3. 调用构造器前,对象已创建好,并且各属性已有默认的初始化的值
  4. 构造器格式(无参)
<权限修饰符> 构造器名() {
    
    
    
}
  1. 构造器和方法的区别:

    1. 没有方法的返回值类型
    2. 方法体内部不能有return语句
    3. 构造器名字 == 类名 (必须)
  2. 构造器的作用

    为类的属性赋值(无参构造器或构造器的重载)

instanceof关键字

  1. 格式:

    a instanceof A:判断对象a是否使A的实例。返回值为bool型(是返回true)

  2. 用法:

    可避免向下转型时出现ClassCastException的异常,即先判断返回true再进行转型。

    (换言之,可以对某个对象进行选择性的转型)

继承

  1. 访问父类的成员变量:super.变量名

    1. 关键字 访问成员变量 访问构造方法
      this this.成员变量
      访问本类成员变量
      this()
      访问本类构造方法
      super super.成员变量
      访问父类成员变量
      super()
      访问父类构造方法
    2. 通过子类对象访问一个方法

      1. 先在子类范围内寻找
      2. 再在父类范围寻找
  2. 子类中所有构造方法被调用时,默认都会先访问父类无参构造方法

    1. 因为子类会继承父类中的数据,可能还会使用父类中的数据。所以子类初始化之前,一定要先完成父类数据的初始化
    2. 每一个子类构造方法的第一条语句默认都是super()
    3. 若使用父类带参构造方法进行数据初始化,即super()
    4. 若父类中没有无参构造方法,只有带参构造方法
      1. 用super关键字去显示的调用父类带参构造方法
      2. 在父类中自己提供一个无参构造方法
  3. 方法重写

    1. 子类出现了和父类中一模一样的方法声明

    2. 应用

      1. 当子类需要父类的功能,而功能的主体子类又自己特有的内容时,可重写父类中的方法,这样即沿袭了父类的功能,又定义了子类特有的内容。

      2. 重写的方法中,可擅用super关键字沿袭父类的(基础)功能

      3. 课用@Override检测重写方法是否有误

      4. 注意事项

        1. 父类中的private方法无法被子类继承,则无法被重写

        2. 子类方法访问权限不能更低

          (public>默认>protected>private)

    3. Java继承的注意事项

      1. 一个子类只能单继承,不支持多继承
      2. 可实现多层继承

多态

  1. 在Java中主要有两种体现形式:

    1. 方法的重载与覆写(重写)
    2. 对象的多态性
  2. 成员访问特点:(为何两种不一样:成员方法有重写)

    1. 成员变量:编译与执行均看左边
    2. 成员方法:编译看左边,执行看右边
  3. 优弊

    1. 优势:提高了程序的扩展性

      ​ 具体体现:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作

    2. 弊端:不能使用子类的特有功能

  4. 转型(实现使用子类特有功能)

    1. 向上转型:从子到父,父类引用指向对象

    2. 向下转型:从父到子,父类引用转为子类对象

      用强制类型转换实现执行子类特有方法(不占用新的堆内存)

抽象类

  1. 概述:

    在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象方法

  2. 特点

    1. 抽象类和抽象方法必须用abstract关键字修饰

    2. 抽象类中不一定有抽象方法,由抽象方法的类一定时抽象类

    3. 抽象类不能直接实例化

      如何实例化:参照多态的方法,通过子类对象实例化,这叫做抽象类多态

    4. 抽象类的子类

      要么重写抽象类中的所有抽象方法

      要么本身就是抽象类

  3. 抽象类成员特点

    1. 成员变量:变量/常量

    2. 构造方法:
      不可直接实例化。
      用于子类访问父类数据的初始化

    3. 成员方法:

      可以有抽象方法:限定子类必须完成某些动作

      也可以有非抽象方法:提高代码的复用性

  4. 抽象类名作为形参和返回值

    1. 方法的形参时抽象类名,其实需要的时该抽象类的子类对象
    2. 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象

接口

  1. Java中的接口更多的体现在对行为的抽象

  2. 声明接口关键字:interface

    public interface <接口名>;

    调用接口关键字:implements

    public class A implements <接口名>;

    接口是abstract的,亦不可直接实例化

  3. 接口多态

    1. 多态的形式:具体类多态,抽象类多态接口多态
    2. 多态的前提:
      1. 有继承或者实现关系;
      2. 有方法的重写/覆写
      3. 有父类/父接口引用指向子/实现类对象
  4. 成员特点

    1. 成员变量:默认被public static final修饰
    2. 成员方法:public abstract
  5. 构造方法

    ​ 接口无构造方法,因为接口主要是行为进行抽象的

    一个类如果无父类,默认继承自Object类

  6. 类和接口的关系

    ​ 一个接口可以implements多个接口

  7. 抽象类和接口的关系

    1. 成员区别

      抽象类 变量,常量;有构造方法;有抽象方法也有非抽象方法
      接口 常量;抽象方法

      2.关系区别

      类与类 只能extends一个父类
      类与接口 可以implements多个接口
      接口与接口 同上

      3.设计理念区别

      抽象类 对象抽象(属性,行为)
      接口 主要对行为抽象
  8. 接口名作为形参和返回值

    1. 方法的形参是接口名,其实需要的是该接口的实现类对象
    2. 方法的返回值是接口名,其实返回的是该接口的实现类对象
  9. JDK8接口的新特性

    1. JDK7及以前,只能定义全局常量和抽象方法(参见4.)

    2. JDK8以后,接口还可以定义静态(static)方法和默认(default)方法。

      1. 接口中定义的静态方法,只能通过接口调用

        interface IA() {
                  
                  
            public static method() {
                  
                  }
        }
        
        public SubClass implements IA {
                  
                  }
        
        public Class SubClassTest {
                  
                  
            public static void main(String[] args) {
                  
                  
                SubClass s = new SubClass();
                
                s.method();			//  ×
                SubClass.method();	//	×
                //上述两种调用方法,(编译时?)会完全无视method方法
                IA.method();		//	√
            }
        }
        
      2. 接口中的默认方法,可通过实现类的对象调用。

      3. 如果子类(或实现类)继承的父类和实现的接口中声明了同名同参的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参的方法(类优先原则)

      4. 如果实现类实现了多个含有同名同参的默认方法的接口,且实现类没有重写此方法的情况下,会报错(接口冲突)(必须重写此方法才可以使用)

      5. 在子类(实现类)调用接口中的方法

        class SuperClass() {
                  
                  
            public void method();
        }
        
        interface CompareA() {
                  
                  
            public static void staticMethod(){
                  
                  }
            public void method();
        }
        
        class SubClass extends SuperClass implements CompareA() {
                  
                  
            public void method();
            
            public void myMethod() {
                  
                  
                method();//调用自己定义的重写的方法
                
                super.method();//调用父类中声明的方法
                
                CompareA.staticMethod();//调用接口中的静态方法
             	CompareA.super.method();//调用接口中的默认类型方法
            }
        }
        

内部类

  1. 访问特点

    1. 内部类可直接访问外部类的成员,包括private
    2. 外部类要访问内部类成员,必须创建对象调用
  2. 成员内部类

    1. 当内部类权限为public时:

      外界使用内部类格式(外部类名.内部类名):

      例:Outer.Inner oi = new Outer().new Inner();

    2. 当内部类权限为private时:

      类似于构建getAge和setAge方法。

  3. 局部内部类

    1. 定义在方法内,外界无法直接访问,需要在方法内部创建对象并使用

    2. 该类可直接访问外部类的成员,也可访问方法内的局部变量

    3. 匿名内部类

      1. 前提:存在一个类或接口,类可以时具体类也可抽象类

      2. 格式:

        new 类名或接口名() {
                  
                  
        	重写方法;
        }
        
      3. 本质:

        是一个继承了该类或实现了该接口的子类匿名对象

      4. 用例:

        不用匿名内部类

        interface A {
                  
                  
            public void printlnfo();
        }
        
        class B implements A {
                  
                  				//定义接口实现类
            public void printlnfo() {
                  
                  		//重写抽象方法
                System.out.println("Hello World!");
            }
        }
        
        class X {
                  
                  
            public void fun1() {
                  
                  
                this.fun2(new B());
            }
            
            public void fun2(A a) {
                  
                  
                a.printlnfo();
            }
        }
        
        public class NoInnerClassDemo01 {
                  
                  
            public static void main(String[] args) {
                  
                  
                new X().fun1();
            }
        }
        

        使用内部类改写:省去写新的实现接口的类

        interface A {
                  
                  
            public void printlnfo();
        }
        
        class X {
                  
                  
            public void fun1() {
                  
                  
                this.fun2(new A() {
                  
                  						//匿名内部类
                    public void printlnfo() {
                  
                  			//实现接口内中的抽象方法
                        System.out.printlnfo("Hello World!");
                    }
                })
            }
        }
        
        public class NoInnerClassDemo02 {
                  
                  
            public static void main(String[] args) {
                  
                  
                new X().fun1();
            }
        }
        

MVC设计模式

  1. MVC将整个程序分为三个层次:视图模型层,控制器层,与数据模型层。

  2. 特点:

    将程序输入输出、数据处理,以及数据的展示分离

  3. 优势:

    使程序结构变的灵活而清晰,同时也描述了程序各个对象间的通信方式,降低了程序的耦合性。

  4. 各层次:

    1. 模型层 model 主要处理数据

      >数据对象封装 model.bean/domain

      >数据库操作类 model.dao

      >数据库 model.db

    2. 控制层

      >应用界面相关 controller.activity

      >存放fragment controller.fragment

      >显示列表的适配器 controller.adapter

      >服务相关的 controller.service

      >抽取的基类 controller.base

    3. 视图层

      >相关工具类 view.utils

      >自定义 view.ui

==与equals()

  1. 对于==运算符(比较的表达式类型必须一致)

    1. 比较基本数据类型变量:比较两个变量包存的数据是否相等
    2. 比较引用数据类型变量:比较两个对象的地址值是否相同,即两个引用是否指向同一个对像实体
  2. 对于equals()方法

    1. 只用于引用数据类型

    2. 源自Object类,其中equals ()的定义:

      public boolean equals(Object obj) {
              
              
          return (this == obj);
      }
      

      说明:和 == 的作用相同,比较两个对象的地址值是否相同。

    3. 其他类自带重写:如String, Data, File, 包装类等

      比较两个对象的实体内容是否相同

    4. String类中的equals()方法重写代码:

      (可用于重写Object类的equals()方法)

      public boolean equals(Object obj) {
              
              
          if (this == anObject) {
              
              
              return true;
          }
          if(anObject instanceof String) {
              
              
              String anotherString = (String)anObject;
              int n = value.length;
              if (n == anotherString.value.length) {
              
              
                  char v1[] = value;
                  char v2[] = anotherString.value;
                  int i = 0;
                  while(n-- != 0) {
              
              
                      if (v1[i] != v2[i])
                          return false;
                      i++;
                  }
                  return true;
              }
          }
          return false;
      }
      

toString()方法

  1. 源自Object类

    其中对toString()的定义:

        public String toString() {
          
          
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    
    
  2. String, Data, File, 包装类等都重写了Object类中toString()方法

    返回实体内容信息

包装类

  1. 作用:将基本类型视为引用类型(对象)

  2. 基本类型 对应的引用类型
    boolean java.lang.Boolean
    byte java.lang.Byte
    short java.lang.Short
    int java.lang.Integer
    long java.lang.Long
    float java.lang.Float
    double java.lang.Double
    char java.lang.Char

    除java.lang.Boolean和java.lang.Char外,其余类的父类为Number

  3. 包装类,基本数据类型,String三者间的转换

    1. 基本数据类型---->包装类

      调用包装类的构造器:

      传入参数为代转换基本数据类型值

    2. 包装类---->基本数据类型

      调用包装类的xxxValue()方法,如:

      Integer in1 = new Integer(10);
      
      int i1 = in1.intValue();
      
    3. 自动装箱与自动拆箱:

      省去调用构造器的过程

      1. 自动装箱如:
      int in1 = 10;
      Integer in2 = in1;//自动装箱
      
      1. 自动拆箱如:
      Integer in1 = new Integer(10);
      int in2 = in1;//自动拆箱
      
    4. 基本数据类型/包装类 ----> String类型

      如:

      	int num1 = 10;
      //方式1:连接运算
      String str1 = num1 + "";
      //方法2:调用String的valueof()方法
      float f1 = 12.3f;
      String str2 = String.valueof(f1);
      
      
    5. String类型 ----> 基本数据类型、包装类

      1. 不能采用强制类型转换的方式(无子父类关系)

      2. 调用parsexxx()方法;

        如:

        String str = "string";
        int num = Integer.parseInt(str);//等号右边返回值即为int类型
        
        //但上述str会导致报错:NumberFormatException
        
  4. 关于包装类wrapper使用的面试题

    1. Object o1 = true ? new Integer(1) : new Double(2.0);
      
      System.out.println(o1);
      

      思考输出结果。 1.0

      解释:三元运算符会在编译时统一左右两边的数据类型,故输出结果为double

    2. Integer m = 1;
      Integer n = 1;
      System.out.println(m == n);
      
      //输出结果为true
      
      Integer m = 128;
      Integer n = 128;
      System.out.println(m == n);
      
      //输出结果为false
      

      解释:自动装箱时会调用Integer类中的一个类叫IntegerCache,里面有个数组叫Integer cache[];默认存储 -128 到 127 int数值。

      而在该范围内比较数组中的地址是缓存里同一个数组Integer cache[]

      若超出范围则new新的,故地址是不同的

单例(Singleton)设计模式

采取某种方法,使某个类只能有一个实例对象

  1. 饿汉式

    class Demo01 {
          
          
        //1.私有化类的构造器
        private Demo01() {
          
          
        }
        
        //2.内部创建类的对象
        //静态方法只能调用静态对象
        private static Demo01 instance = new Demo();
        
        //3.提供公共的静态的方法(方便外部获取单例对象),返回类的对象
        public static Demo01 getInstance() {
          
          
            return instance;
        }
    }
    
  2. 懒汉式

    class Demo02 {
          
          
        1.私有化类的构造器
        private Demo02() {
          
          
        }
        
        //2.声明当前类对象(静态)(无初始化)
        private Demo02 instance = null;
        
        //3,声明公共的静态的返回当前类对象的方法
        public static Demo02 getInstance() {
          
          
            if (instance == null) {
          
          				//增加判断条件,保证instance严格只有一个
      			instance = new Demo02();     
            	return instance; 
        
            }
        }
    }
    
  3. 对比

    1. 饿汉式:

      利:线程安全

      弊:对象一开始就创建,(加载时间长)

    2. 懒汉式:

      利:用的时候再创建对象

      弊:目前写法,线程不安全:如,在用户A进入if内,instance还未被new的时候发生线程堵塞,用户B可以在此时也进入if内,则两者分别new了一次。

  4. 单例模式的优点:

    由于单例模式只生成一个实例,减少了系统性能的开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

    如java.lang.Runtime:

    public class Runtime {
          
          
        private static final Runtime currentRuntime = new Runtime();
    
        private static Version version;
    
        public static Runtime getRuntime() {
          
          
            return currentRuntime;
        }
    
        /* Don't let anyone else instantiate this class */
        private Runtime() {
          
          }
        ......
    }
    
  5. 其他应用场景

    1. 网站的计数器,一般也是单例模式实现,否则难以同步。
    2. 应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
    3. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
    4. 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。
    5. Application也是单例的典型应用
    6. Windows的Task Manager(任务管理器)就是很典型的单例模式
    7. Windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

异常处理

  1. 概述:

    规避一些非代码问题如,客户输入数据的格式,读取文件是否存在,网络是否始终保持通常等等

    语法错误和逻辑错误不是异常。

    分类:

    1. Error:JVM无法解决的严重问题,如JVM系统内部错误,资源耗尽等严重情况。如,StackOverflowError和OOM(堆溢出)。一般不编写针对性的代码进行处理。
    2. Exception:其他因编程错误或偶然的外在因素导致的一般性问题,可以用针对性的代码进行处理。如空指针访问,试图读取不存在的文件,网络连接中断,数组下标越界等。
  2. 常见异常,参见https://www.jianshu.com/p/a03c8807bbbc

  3. 异常处理模型:抓抛模型

    1. 过程一:“抛”,程序在正常执行过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。并将此对象抛出。一旦抛出对象,try内其后的代码就不再执行。

    2. 过程二:“抓”,可以理解为异常的处理方式:

      1. try-catch-finally

        1. 格式:
        try{
                  
                  
            //可能出现的代码
        }catch(异常类型1 变量名1){
                  
                  
            //处理异常的方式1
        }catch(异常类型2 变量名2){
                  
                  
            //...
        }//可多个catch
        ......
        //可选是否使用finally
        finally{
                  
                  
            //一定会执行的代码
        }    
        
        1. 要点:

          1. finally可选

          2. try内代码出现异常,会生成一个对应异常类的对象,根据此对象的类型,去catch中匹配。

          3. 匹配到catch后进行异常处理,完成后寻找fianlly执行(也可能无),随后进行执行后面的代码。

          4. catch中的异常类型若无子父类关系,则上下顺序无所谓。

            若有子父类关系,要求子类一定声明在父类上面,否则会报错。

          5. 常用的异常对象处理方式:

            1. String getMessage()
            2. printStackTrace()
          6. 在try结构中声明的变量,等结束try的使用后,就不能再被调用!

          7. 可以嵌套

          8. 使用try-catch-finally处理编译时异常,相当于将一个编译时可能出现的异常,延迟到运行时出现。

          9. 由于运行时异常比较常见,所以我们通常不针对运行时异常编写try-catch-finally了。针对编译时异常,我们一定要考虑异常的处理。

      2. throws + 异常类型

        1. 写在方法声明处,指明此方法执行时,可能会抛出的异常类型。一旦方法执行时,出现异常,仍会在异常代码处生成一个异常类的对象。此对象满足throws后异常类型时,就会被抛出。异常后续的代码不再执行。

        2. throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉。

          真正处理掉的时try-catch-finally的方式

    3. 如何选择两种方式

      1. 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws。意味着如果子类重写的方法中有异常,必须使用try-catch-finally方式处理。
      2. 执行的方法a中,先后又调用的另外的几个方法,这几个方法时递进关系执行的,则可以使用throws的方式进行处理,而执行的方法a可以使用try-catch-finally方式。
  4. 手动抛出异常(throw)

    1. 区别于系统自动生成的异常类型如FileNotFoundException等。

    2. 例子

      public class StudentTest {
              
              
          try {
              
              
              Student s = new Student();
              s.regist(-1001);
              System.out.println(s);
          } catch (Exception e) {
              
              
              //e.printStackTrace();
              System.out.println(e.getMessage));
          }
      }
      
      class Student {
              
              
          private int id;
          public void regist(int id) throws Exception {
              
              
              if (id > 0) {
              
              
                  this.id = id;
              }else{
              
              
                  //System.out.println("您输入的数据非法!");
                      //手动抛出异常:
                      //throw new RuntimeException("您输入的数据非法!")//不用在实现类里使用try-catch,因为类型为“运行时的错误“
                      throw new Exception("您输入的数据非法!")//需要在实现类里加try-catch,因为Exception类型考虑了编译时出现的问题。
              }
          }
      }
      
  5. 用户如何自定义异常

    1. 继承于现有的异常结构:RuntimeException, Exception。
    2. 提供全集变量类序号:serialVersionUID(static final long)
    3. 提供重载的构造器

猜你喜欢

转载自blog.csdn.net/qq_40463117/article/details/112683956