Java易错知识点整理

Java易错知识点整理

栈和堆

新建一个对象——放在栈里    int[] array;

堆,内存里———— array =new int[10];

关于java抽象override

类无法访问父类的private字段或者private方法。protected的变量或者方法可以访问

子类必须重写父类的构造方法

子类必须重写抽象类的抽象方法

在Java中,一个类只能继承自另一个类,不能从多个类继承。但是,一个类可以实现多个interface

抽象类和接口的对比如下:

abstract classinterface
继承只能extends一个class可以implements多个interface
字段可以定义实例字段不能定义实例字段
抽象方法可以定义抽象方法可以定义抽象方法
非抽象方法可以定义非抽象方法可以定义default方法

super

super关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName。例如:public class Main {

 public static void main(String[] args) {
       Student s = new Student("Xiao Ming", 12, 89);
    }
}

class Person {
    protected String name;
    protected int age;
    
    public Person(String name, int age) {
    this.name = name;
    this.age = age;
}
}
class Student extends Person {
    protected int score;
    
    public Student(String name, int age, int score) {
    this.score = score;
}
}
Main.java:21: error: constructor Person in class Person cannot be applied to given types;
    public Student(String name, int age, int score) {
                                                    ^
  required: String,int
  found:    no arguments
  reason: actual and formal argument lists differ in length
1 error
error: compilation failed

这是因为在Java中,任何class的构造方法,第一行语句必须是调用父类的构造方法。如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super();,所以,Student类的构造方法实际上是这样:

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        super(); // 自动调用父类的构造方法
        this.score = score;
    }
}

因此我们得出结论:如果父类没有默认的构造方法,子类就必须显式调用super()并给出参数以便让编译器定位到父类的一个合适的构造方法

这里还顺带引出了另一个问题:即子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的。

抽象类

如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。

因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。

使用abstract修饰的类就是抽象类。我们无法实例化一个抽象类:

Person p = new Person(); // 编译错误

无法实例化的抽象类有什么用?

因为抽象类本身被设计成只能用于被继承,因此,抽象类可以强迫子类实现其定义的抽象方法,否则编译会报错。因此,抽象方法实际上相当于定义了“规范”。

例如,Person类定义了抽象方法run(),那么,在实现子类Student的时候,就必须覆写run()方法:

1.构造方法与构造器

有两种类型的构造函数

  • 默认构造函数(无参数构造函数)

    public People( ){

    }

  • 参数化构造函数

    public People(String name){

    }

    一、this关键字主要有三个应用:
    (1)this调用本类中的属性,也就是类中的成员变量;
    (2)this调用本类中的其他方法;
    (3)this调用本类中的其他构造方法,调用时要放在构造方法的首行。
    Public Class Student {
    String name; //定义一个成员变量name
    private void SetName(String name) { //定义一个参数(局部变量)name
    this.name=name; //将局部变量的值传递给成员变量
    }
    }

继承

提高了代码的复用性

提高了代码的维护性

变量的访问特点:子类访问变量的顺序

1:在子类方法内部

2.子类的的成员变量

3.再去父类的成员变量

4.如果都没有,就报错,不考虑父类的父类

super和this的区别

父类空间优先于子类对象产生 在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空 间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构 造方法调用时,一定先调用父类的构造方法。理解图解如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dgY8lMhM-1617268870562)(Java易错知识点整理.assets/image-20210320113738753.png)]

super和this的含义

super :代表父类的存储空间标识(可以理解为父亲的引用)。

this :代表当前对象的引用(谁调用就代表谁)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zkeM593c-1617268870565)(Java易错知识点整理.assets/image-20210320103047487.png)]

  1. 访问成员
this.成员变量 ‐‐ 本类的
super.成员变量 ‐‐ 父类的
this.成员方法名() ‐‐ 本类的
super.成员方法名() ‐‐ 父类的

  1. 访问构造方法

    this(...) ‐‐ 本类的构造方法
    super(...) ‐‐ 父类的构造方法
    

    子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。 super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

方法重写

成员方法重名——重写(Override)

如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。

方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。

重写的应用

子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。

class Phone {
    public void sendMessage(){
        System.out.println("发短信");
    }
    public void call(){
        System.out.println("打电话");
    }
    public void showNum(){
        System.out.println("来电显示号码");
    }
}

/*  小贴士:这里重写时,用到super.父类成员方法,表示调用父类的成员方法。
  注意事项
  1. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
  2. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
  1.5 继承后的特点——构造方法
  当类之间产生了关系,其中各类中的构造方法,又产生了哪些影响呢?
  首先我们要回忆两个事情,构造方法的定义格式和作用。
  1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构
  造方法中默认有一个 
  super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。代
  码如下:*/
//智能手机类
class NewPhone extends Phone {
    //重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
    public void showNum(){
//调用父类已经存在的功能使用super ---------调用父类的方法
        super.showNum();
//增加自己特有显示姓名和图片功能
        System.out.println("显示来电姓名");
        System.out.println("显示头像");
    }
}
public class ExtendsDemo06 {
    public static void main(String[] args) {
// 创建子类对象
        NewPhone np = new NewPhone()// 调用父类继承而来的方法
        np.call();
// 调用子类重写的方法
        np.showNum();
    }
}

注意事项
  1. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。 (public>默认>private)
  2. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

权限修饰符

public:公共的。

protected:受保护的

default:默认的

private:私有的

可见,public具有最大权限。private则是最小权限。

编写代码时,如果没有特殊的考虑,建议这样使用权限:

成员变量使用 private ,隐藏细节。

构造方法使用 public ,方便创建对象。

成员方法使用 public ,方便调用方法。

小贴士:不加权限修饰符,其访问能力与default修饰符相同

final关键字

学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承 API中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的情况,Java提供了 final 关键字, 用于修饰不可改变内容。

final: 不可改变。可以用于修饰类、方法和变量。

类:被修饰的类,不能被继承。

方法:被修饰的方法,不能被重写。

变量:被修饰的变量,不能被重新赋值。

Static关键字

非静态的成员方法

能访问静态成员变量

能访问非静态成员变量

能访问静态成员方法

能访问非静态成员方法

静态的成员方法

能访问静态成员变量

能访问静态成员方法

接口Interface

public interface 接口名称 {
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
}

含有抽象方法

抽象方法:使用 abstract 关键字修饰,可以省略没有方法体。该方法供子类实现使用。

public interface InterFaceName {
public abstract void method();
    void method();
}

含有默认方法和静态方法

默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。 静态方法:使用 static 修饰,供接口直接调用。基本的实现

public interface InterFaceName {
public default void method() {
// 执行语句
}
public static void method2() {
// 执行语句
}
}

基本的实现

类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。

实现的动作类 似继承,格式相仿,只是关键字不同,实现使用 implements 关键字。

非抽象子类实现接口:

  1. 必须重写接口中所有抽象方法。
  2. 继承了接口的默认方法,即可以直接调用,也可以重写。

迭代器Iterator

Iterator的定义如下:

public interface Iterator<E> {}

default void forEachRemaining(Consumer<? super E> action) 
执行给定的每个剩余元素的动作,直到所有的元素都被处理或操作抛出异常。  
boolean hasNext() //判断是否有元素没有被遍历
返回 true如果迭代具有更多的元素。  
E next() 
返回迭代中的下一个元素。  
default void remove() 
从基础集合中移除这个迭代器返回的最后一个元素(可选操作)。  

实现:

// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;

public class RunoobTest {
    public static void main(String[] args) {

        // 创建集合
        ArrayList<String> sites = new ArrayList<String>();
        sites.add("Google");
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");

        // 获取迭代器
        Iterator<String> it = sites.iterator();

        // 输出集合中的所有元素,循环输出
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

https://www.runoob.com/java/java-iterator.html

增强for循环

JAVA中的增强for循环底层是通过迭代器模式来实现的。

//定义格式
    for(变量类型 变量:需迭代的数组或集合){

}


for (int i = 0; i < list.size(); i++) {
 System.out.print(list.get(i) + ",");
}

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
 System.out.print(iterator.next() + ",");
}

for (Integer i : list) {
 System.out.print(i + ",");
}

Hash

文档:

hashCode
public int hashCode()
返回一个对象的哈希代码值。这种方法对于hash表,如所提供的 HashMap利益支持。 
对hashCode一般合同:

如果根据equals(Object)法两个对象是相等的,那么调用hashCode方法每一个对象必须产生相同的整数结果。 
它不是必需的,如果按照equals(java.lang.Object)法两个对象是不平等的,然后调用hashCode方法每一个对象必须产生不同的整数结果。然而,程序员应该意识到,产生不同的整数结果的不平等的对象可能会提高哈希表的性能。 
    
尽合理的切实可行,由类Object定义hashCode方法返回不同的对象不同的整数。(这通常是通过将该对象的内部地址转换成一个整数,但这不是实现实现技术的™java编程语言。要求)

结果 
此对象的哈希代码值。 
另请参见: 
equals(java.lang.Object), System.identityHashCode(java.lang.Object) 

冒泡排序

import java.util.Arrays;

//排序代码
public class Bubble {
    /*
    对数组a中的元素进行排序
    */
    public static void sort(Comparable[] a) {				
 													/*
 													i
 													4 8 6 7 5 3
 													0 1 2 3 4 5    length=6
 													  j	j	
 													*/
        for (int i = a.length - 1; i > 0; i--) {   //for(int i=0;arr<arr.length-1;i++)
            for (int j = 0; j < i; j++) {		// for(int j=i+1;j<arr.length,j++)
                if (greater(a[j], a[j + 1])) {		if(greater(arr[i],arr(j)))
                    exch(a, j, j + 1);
                }
            }
        }
    }

    /*
    比较v元素是否大于w元素
    */
    private static boolean greater(Comparable v, Comparable w) {
        return v.compareTo(w) > 0;
    }

    /*
    数组元素i和j交换位置
    */
    private static void exch(Comparable[] a, int i, int j) {
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

    public static void main(String[] args) {
        Integer[] a = {4, 5, 6, 3, 2, 1};
//        Bubble bubble =new Bubble();
        bubble.sort(a);
        Bubble.sort(a);
        System.out.println(Arrays.toString(a));
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值