Java易遗忘知识点

Java易遗忘知识点

1. java类基础知识

javac :将代码(.java)编译成字节码文件(.class),如javac HelloWord.java

java :对字节码文件进行解释,如java HelloWord

一个Java文件里面可以有多个class(内部类),但是只能有一个public class

是java中最基本的逻辑单元

严格来说,main函数不属于类的成员方法,也无法被其他方法/类调用。

String[] argsmain函数的形参,args是变量名可以改变。此参数可以接收外界提供给main函数的参数。

1.2 基本类型和选择结构

整形:

  • short:2个字节,16位,表示范围 − 2 − 15 -2^{-15} 215~ ( 2 15 − 1 ) (2^{15}-1) (2151)
  • int:4个字节,32位,表示范围 − 2 − 31 -2^{-31} 231 ~ ( 2 31 − 1 ) (2^{31}-1) (2311)
  • long:8个字节,64位,表示范围 − 2 − 63 -2^{-63} 263 ~ ( 2 63 − 1 ) (2^{63}-1) (2631)

浮点数:

  • float:4个字节,32
  • double:8个字节,64
  • 两者的表示都是采用IEEE 754标准,都不能表示精确的数字。

在java中if的判断条件只能是布尔值布尔表达式,不可以是单个数字啥的,区别于C。

1.3 重载及权限修饰符

函数重载(overload),在同一个类中,方法名可以相同,但是参数类型参数个数必须不同。
tips:在jdk1.5以后,允许重载的方法返回值是协变的


修饰符类内同包不同包子类不同包非子类
private×××
(default)××
protected×
public

private修饰的变量或方法,只有在同一个类的内部被访问。

default不是修饰符,只是为了方便才叫他的default的,如果不写修饰符,那就认为是default。其修饰的变量及方法只能在一个包中的类才能使用。

protected修饰的变量或方法可以在类内、同包内及不同包的子类所访问。

public修饰的变量或方法可以在不同包中使用。

privatedefaultprotected只能修饰内部类。public可以修饰所有的类。

2. 面向对象和类

2.1 对象与基本类型的赋值

  • 对象赋值是reference赋值(相当于C的指针),而基本类型是直接值拷贝

    • 在这里插入图片描述
  • 类成员变量有初值,函数中的临时变量必须要有初始值。

2.2 构造函数

  • 在java中有构造函数,无析构函数,因为java具有 内存自动回收机制,当变量退出其生命周期后,JVM会自动回收所分配的对象的内存。

  • 构造函数的名称与类名一致,且没有返回值。

  • 当你没有实现构造函数时,Java编辑器会自动帮该类产生一个无参构造函数。

3. 继承、抽象类和接口

继承:子类可以继承其父类,其父父类…所有的属性和方法,但不能直接访问父类的private成员。

关键字:extends

  • java采用的是单继承,即每个类只能有一个父类。【注意】如果不写extends 则每个类默认都继承一个java.lang.Object 。又因为,子类会继承其父类、父父类…所有的属性和方法,所以可以认为每个类都继承了java.lang.Object

  • 每个子类的构造函数的第一句话都默认调用父类的无参构造函数super(),除非在子类的第一句代码就自己写了super语句。也就是说子类的构造函数第一行必须调用父类的构造函数

  • 子类使用父类的属性:super.属性名。如果是在子类的静态方法里面,可以直接调用父类的静态属性即可以省略super

  • 子类使用父类的方法:super.方法名() 。需要注意的是子类不可以重写父类的静态或私有方法,但可以调用和重新定义。

    只有override注释的才是真正的重写,没加的都是伪重写(实际要叫重新定义)
    在这里插入图片描述
    在这里插入图片描述
    运行结果:
    在这里插入图片描述
    说明在省略@override的前提下,子类并不会真正的重写父类的私有或者静态方法 ,只有父类的方法跟属性被public修饰时,才可以省略@override


抽象类:使用abstract声明的类,包含了任意零个或多个的 属性,完整的方法和抽象方法(abstract定义的)。

关键字:abstract

【注意】

  1. 只有全部方法都是完整的才可以实例化(new)。
  2. 包含了抽象方法的一定是抽象类,抽象类不一定包含抽象方法。
  3. 子类可以继承抽象类,但只有实现了父类的所有抽象方法,才可以变成完整类,不然它还是抽象类。

比如下面AB都是抽象类

public abstract class A{
    int a;
    // 无参构造函数
    public A(){}
    
    public void test(){
        a++;
    }
    // 抽象方法
    public abstract int sum(){};
}
public abstract class B{
    int b;
    public void test(){
        b++;
    }
}

接口:使用interface声明,所有方法都是public修饰的,并且方法体里面都无代码且最后以分号结尾。

接口中可以定义变量,但必须是常量(public staic final修饰),如果未写修饰符,默认就是public staic final.

比如

public interface A(){
    // public static final int a;
    int a;  // 两者等价
    
    public int sum();
    public void eat();
    public void walk();
}
  • 在java中,类只能单继承,但可以实现多个接口,且继承类的同时可以实现接口。
  • 接口实现接口时,没有实现的方法会叠加。
  • 类实现接口时,必须实现接口中所有的方法。

总结

抽象类和接口的相同点:两者都不能被实例化(new)

抽象类和接口的不同点

  1. 抽象类用abstract声明,接口使用interface 关键字
  2. 抽象类可以有部分函数是完整实现的,接口中所有方法都不能是完整实现的。
  3. 一个类只能继承一个抽象类,但可以实现多个接口。【注意】extends要写在implements前面
  4. 抽象类有构造函数,接口无构造函数。
  5. 抽象类可以有main,接口中没有main
  6. 抽象方法可以有多个权限修饰符,接口的中方法只能是public

3.1 转型、多态

转型

子类可以转为父类,父类不可以转为子类,除非父类本身就是从子类转化而来。

比如Human为父类,Man为子类

// 子向父转型
Man man = new Man();
Human obj1 = (Human) man;

// 父转型子的特殊情况
Human obj2 = new Man();
Man man = (Man)obj2;

多态

子类重新定义了父类的方法(名字、参数一致)的行为叫做重写(overwrite)。

子类向父类转换,并且子类重写了父类的方法,这种行为就叫做多态。我们称重载为编译时多态,重写为运行时多态

子类方法的优先级高于父类。

作用:

  • 以统一的接口来操纵某一类中不同对象的动态行为。

    • Human[] hus = new Human[3];
      hus[0] = new Man();
      hus[1] = new Man();
      hus[2] = new Woman();
      
      for(int i=0;i<Human.length;i++){
          // 每个对象都执行eat方法
          hus[i].eat();
      }
      
  • 对象之间的解耦(这种方式也叫契约设计

    • public staic void haveLunch(Human hu){
          // 不同对象进来就执行不同的eat方法
          hu.eat();
      }
      
      public static void main(String[] args){
          Human[] hus = new Human[3];
          hus[0] = new Man();
          hus[1] = new Man();
          hus[2] = new Woman();
      
          for(int i=0;i<Human.length;i++){
              // 每个对象都执行eat方法
             haveLunch(hus[i]);
          }
      }
      

4. static、final和常量设计

static

  • static可作用在变量方法代码块

  • static变量只依赖于类存在,即通过类名即可访问。(当然也可以使用对象名来调用)

  • 同一类中的static变量都存储在同一空间(栈)中,所有的对象实例都可以共享该空间

    • public class Potato(){
          static int price;
          String name;
          
          public Potato(int price, String name){
              this.price = price;
              this.name = name;
          }
          
      	public static void main(String args[]){
              Potato p1 = new Potato(20, "爆炒土豆丝");
              
              Potato p2 = new Potato(25, "黄焖土豆丝");
          }
      }
      

      在这里插入图片描述

  • static方法,也是可以直接通过类名来调用。static方法里面的所有东西都必须是静态的,比如静态方法里面禁止调用非静态方法,不可以使用非静态变量。【注意】非静态方法可以调用静态方法

  • static修饰代码块。static代码块只会在类第一次加载时被调用,即在程序运行期间,static代码块只会运行一次。【注意】执行顺序static块 > 匿名块 > 构造函数

    class StaticBlock(){
        // 静态代码块
        static {
            System.out.println("0000");
        }
        // 构造函数
        public StaticBlock(){
            System.out.println("1111");
        }
        // 匿名代码块
        {
            System.out.println("2222");
        }
    }
    

    创建StaticBlock对象时,得到的结果为:0000 2222 1111

单例模型

定义:限定某一类在整个程序运行过程中,内存空间中只能保留一个实例对象。

实现思想:采用static共享对象实例,采用private修饰构造函数来防止外界new操作,向外界提供共享对象。

代码实现:

public class SingleTon{
    // 共享同一个对象
    static SingleTon obj = new SingleTon();
    // 防止外部new
    private SingleTon(){
    }
    // 向外界提供实例对象
    public static SingleTon getInstance(){
        return obj;
    }
    
    public static void main(String args[]){
        SingleTon s1 = SingleTon.getInstance();
        SingleTon s2 = SingleTon.getInstance();
        System.out.println(s1==s2); // true
    }
}

final

  • final修饰的类不能被继承
  • 父类中final修饰的方法不能被子类改写
  • final修饰的变量
    • 对象:不能修改其指针,但可以修改其内部的值
    • 基本类型的变量:不能修改其值。

4.1 常量池

C语言的常量定义:const

java的常量定义:public static final 。常量名建议全大写,以连字符_相连。

常量池:位于****空间中。相同的值只存储一份,节省内存,共享访问。

java给字符串、很多基本类型的包装类都建立了常量池。

拥有常量池包装类:(超过范围就被赶出常量池)

  • Boolean:true,false
  • Byte:-128~127
  • Character:0~127
  • Short、Integer、Long:-128~127
  • 【注意】FloatDouble没有常量池

代码演示:

public class Test(){
	public static void main(String args[]){
        Boolean b1 = true;
        Boolean b2 = true;
        System.out.println(b1==b2);  // true
        
        Integer i1 = -128;
        Integer i2 = -128;
        System.out.println(i1==i2);  // true
        
        Integer i3 = 128; // 超出范围
        Integer i4 = 128;
        System.out.println(i3==i4);  // false
        
        Float f1 = 0.5;
        Float f2 = 0.5;
        System.out.println(f1==f2);  // false
        
        String s1 = "abcd";
        String s2 = "a"+"bc"+"d";  // 都是常量,编译器会自动优化
        System.out.println(s1==s2);  // true
    }
}

字符串跟包装类都有两种创建方式:

  • 字面量:此方式创建的变量会放在****空间中,如String a = “abc”Integer i = 10
  • new:此方式创建的变量会放在****空间中,如String a = new String("abc")Integer i = new Integer(10)

tips:栈内存容量小,读取速度快;堆内存容量大,读取速度慢。

【知识点】

  1. 基本类型跟包装类之间会自动 装箱拆箱。
  2. 加法+操作会使包装类自动 拆箱。
public class Test(){
	public static void main(String args[]){
        int i1 = 10;  // 存在于栈中常量池
        Integer i2 = 10;  // 存在于栈中常量池
        // 基本类型跟包装类进行比较,包装类自动拆箱
        System.out.println(i1 == i2);  // true
        
        Integer i3 = new Integer(10);  // 存在于堆
        // 基本类型跟包装类进行比较,包装类自动拆箱
        System.out.println(i1 == i3);  // true
        // 两个对象进行比较,判断其地址
        System.out.println(i2 == i3);  // false
        
        Integer i4 = new Integer(5); 
        Integer i5 = new Integer(5);
        // 加法操作会使包装类自动拆箱。i4+i5=10,10为int类型
        System.out.println(i1 == (i4+i5));  // true
        System.out.println(i2 == (i4+i5));  // true
        System.out.println(i3 == (i4+i5));  // true
        
        Integer i6 = i4+i5; // 先拆箱再装箱,最后等价于Integer i6 = 10
        System.out.println(i1 == i6);  // true
        System.out.println(i2 == i6);  // true
        System.out.println(i3 == i6);  // false
    }
}

【知识点】

  1. 字符串有 变量或对象 参与相加时不进行优化
  2. euqals:同类型同内容才会返回true
  3. == :两个都是对象(相同类型)时,比较地址;至少有一个是基本类型时,比较值
public class Test(){
	public static void main(String args[]){    
        String s1 = "abcd"; // 位于栈中
        String s2 = "abc"; // 位于栈中
        String s3 = s2 + "d"; // 位于堆中
        // 有变量相加,不进行优化
        System.out.println(s1==s3); // false
        // euqals是比较字符串内容
        System.out.println(s1.equals(s2)); // true
        
        String s4 = new String("abc"); // 位于堆中
        System.out.println(s2==s4); // false
        
        String s5 = "abc" + new String("d"); // 位于堆中
        System.out.println(s1==s5); // false
        System.out.println(s3==s5); // false
    }
}

4.2 不可变对象

不可变对象一旦创建就不可更改,其包括:

  • 八个基本类别的包装类
  • String,BigInteger等

优点

  1. 只读,线程安全
  2. 重复使用,提高性能

缺点:制造垃圾,浪费空间

不可变对象在赋值传参的时候也是传指针。例如:
在这里插入图片描述

如果需要对字符串进行大量的修改操作,那么这种方式会大大降低性能,我们可以使用StringBufferStringBuilder类的append方法来进行修改。

  • StringBuffer / StringBuilder 的对象都是可变对象
  • StringBuffer 是同步的,线程安全,修改快速
  • StringBuilder 不同步,线程不安全,修改更快
    在这里插入图片描述

他们的方法用法一样只是同不同步的问题:

  • append / insert / delete
  • substring(int beginIndex, int endIndex):返回字符串的子字符串(左闭右开)
  • length() 字符串实际大小。capacity() 占用空间大小。如果append的对象很长,超过了capacity的大小,那么capacity的大小会乘2加1。如果扩容后的capacity还不够,此时capacity直接等于字符串长度。
  • replace(charStr, replStr) / repalceAll(charStr, replStr) :都会用replStr全部替换charStr。只不过前者的charStr纯字符,而后者的charStr正则表达式

5. Java常用类

包名以Java开头的包是Java的核心包

包名以Javax开头的包是Java的扩展包


5.1 数字类(BigInteger和BigDecimal)

BigIntegerBingDecimal分别是大整数类跟大浮点数类。

有多大呢?你的内存有多大他就可以表示多大。

它们不支持+-*/,但有共同的方法可以做加减乘除:

  • add():加法操作
  • subtract():减法操作
  • multipy():乘法操作
  • divide():除法操作
  • max():求两者较大值
  • min():求两者较小值
  • equals():判断是否相等
  • divideAndRemainder():求余数(返回的是数组)

BigInteger

import java.math.BigInteger

public class Test(){
	public static void main(String args[]){
        // 使用字符串创建,使用数字的话会有误差
        BigInteger s1 = new BigInteger("987654321");
        BigInteger s2 = new BigInteger("123456789");

        System.out.println("加法操作:"+ s1.add(s2));
        System.out.println("减法操作:"+ s1.subtract(s2));
        System.out.println("乘法操作:"+ s1.multiply(s2));
        // 【注意】只会保留整数
        System.out.println("除法操作:"+ s1.divide(s2));
        System.out.println("最大值:"+ s1.max(s2));
        System.out.println("最小值:"+ s1.min(s2));

        // 求余数
        BigInteger result[] = s1.divideAndRemainder(s2);
        System.out.println("商是:"+ result[0]+ "; 余数是:"+ result[1]);

    }
}

BigDecimal

import java.math.BigDecimal

public class Test(){
	public static void main(String args[]){
        // 使用字符串创建,使用数字的话会有误差
        BigDecimal s1 = new BigDecimal("987654321.123456789");
        BigDecimal s2 = new BigDecimal("123456789.987654321");

        System.out.println("加法操作:"+ s1.add(s2));
        System.out.println("减法操作:"+ s1.subtract(s2));
        System.out.println("乘法操作:"+ s1.multiply(s2));
        // 【注意】可以指定小数点位数,以及舍入方法(这里是四舍五入)
        System.out.println("除法操作:"+ s1.divide(s2, 6, RoundingMode.HALF_UP));
        System.out.println("最大值:"+ s1.max(s2));
        System.out.println("最小值:"+ s1.min(s2));

        // 求余数
        BigInteger result[] = s1.divideAndRemainder(s2,);
        System.out.println("商是:"+ result[0]+ "; 余数是:"+ result[1]);

    }
}

6. Java数据结构

6.1 数组

  • 存放的数据都是同一种类型
  • 所有数据线性排列
  • 需明确容器长度
  • 可通过位置索引快速定位数据

数组定义方式:

// 数组声明
int a[];
int[] b;  // 推荐

// 数组初始化
b = new int[5];  // 开辟5个空间

// 声明的同时初始化
int[] b = new int[5];
int[] b = {1,2,3};
// 错误示范:int[5] b;

数组遍历:

【注意】数组的长度是length属性;字符串的长度是**length()方法**

int[] arr = new int[5];
// 第一种
for(int i=0;i<arr.length;i++){
    System.out.println(arr[i]);
}
// 第二种 不用担心数组越界
for(int i:arr){
    System.out.println(i);
}

多维数组:

// 多维数组
int arrs[][] = new int[2][3]; // 规则数组,两行三列
int d[2][]; // 不规则数组
d[0] = new int[1]; //第一行只有一列
d[1] = new int[3]; // 第二行有三列

// 多维数组的遍历方式也有两种

// 第一种
for(int i=0;i<arrs.length;i++){  // 行数
    for(int j=0;j<arrs[i].length;i++){ //列数
        System.out.println(arrs[i][j]);
    }
}
// 第二种
for(int[] arr:arrs){  // 行数
    for(int a:arr){ //列数
        System.out.println(a);
    }
}

6.2 列表List

  • 有序的Collection
  • 允许重复元素
  • 里面的每个数据都只能是对象,就算是由int类型它也会自动装箱。

主要实现:ArrayList(非同步)LinkedList(非同步)Vector(同步)

三者共同的方法

  • add([index], value):在index处添加value,如果没指定index则默认最后。
  • remove(index):删除index处的元素
  • get(index):获取index处的元素
  • size():返回列表大小

三种遍历方法:Iterator(快)for+get方式(最慢)for-each(最快)


ArrayList

  • 可变数组实现的List,不支持同步
  • 具有数组的特点。它不适合经常插入删除,主要用于查询数据
  • 跟数组相比可以动态扩容。容器每次满了的时候都会扩容一半。

创建:ArrayList<Integer> a = new ArrayLsit<Integer>();

ArrayList<Father> a = new ArrayLsit<Son>(); (多态)

LinkedList

  • 双向链表实现的List,不支持同步
  • 顺序访问高效,插入删除高效
  • 适合经常变化的数据

特有方法:

  • addFirst(value):在头部添加数据
  • getFirst(value):获取头部的数据

创建:LinkedList<Integer> linklist = new LinkedList<Integer>();

Vector

  • 适合多线程
  • 可变数组实现的List

创建:Vector<Integer> linklist = new Vector<Integer>();


6.3 集合Set

  • 确定性:对任何对象都能判定其是否属于某一个集合
  • 互异性:每个元素是不一样的。(内容不一样)
  • 无序性:集合内的元素无先后顺序
  • 每个数据都只能是对象

主要实现:HashSet(非同步)LinkedHashSet(非同步)TreeSet(非同步)

三者共同的方法

  • add(value):增加一个元素。可以增加null元素(除了TreeSet
  • clear():清空整个集合
  • contains(value):判断是否包含value元素
  • remove(value):删除value
  • size():获取集合大小
  • retainAll(Set2):计算两个集合的交集

HashSet

  • 基于散列函数的集合
  • 数据无先后顺序

创建:HashSet<Integer> hashset = new HashSet<Integer>();

LinkedHashSet

  • 基于散列函数双向链表的集合
  • 元素有先后顺序

创建:LinkedHashSet<Integer> linkSet = new LinkedHashSet<Integer>();

TreeSet

  • 基于树结构(TreeMap) 的集合
  • 不可以容纳null
  • 元素自动排序,遍历输入的话会从小到大输出。

创建:TreeMap<Integer> treeMap = new TreeMap<Integer>();


HashSetLinkedHashSet判定重复元素的原则:

  1. 先判断两个元素的hashCode方法(计算对象信息和内存地址)的返回值是否相同,若不同返回false。
  2. 若相同,则使用equals方法判断,若不同返回false;否则返回true。

TreeSet判断重复元素的原则是 使用compareTo方法(需实现comparable接口)

tips:

  • hashCode和equals方法是在Object类中的,所以每个类都有。
  • 使用equals判断相等的,那他们的哈希值(hashCode的返回值)一定相等
  • 如果哈希值相等,equals判断的值未必相等。

6.4 映射Map

  • 每个元素都是键值对,即{key, value}的形式,k都不允许为null且不能重复。
  • 一个输入对应一个输入

主要实现:HashMap(非同步,快,数据量大)

常用方法:

  • clear():清空数据
  • contains(value):等同于containsValue(value),判断是否包含value
  • containsKey(key):判断是否存在key
  • get(key):获取该key的value
  • put(key, value):新增或修改key
  • remove(key):删除该k-v
  • size():返回数据大小

HashMap创建方式:HashMap<Integer,String> hashMap = new HashMap<Integer,String>();


6.5 工具类

6.5.1 Arrays类

  • 处理对象是数组
  • sort():对数组排序
  • binarySearch():使用二分查找来查找元素。查找成功返回下标,失败返回 -1
  • copyOf():批量复制
  • fill():批量赋值
  • equals():等价性比较
int[] a={3,1,2};
Arrays.binarySearch(a, 1);  // 1
Arrays.sort(a);
int[] b = Arrays.copyOf(a, 2);

在这里插入图片描述

6.5.2 Collections类

  • 处理对象基本为List
  • 也有排序,查找,赋值
  • 还可以查找集合的最大值最小值
  • 反序排列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值