【Java】从基础开始的笔记-持续更新

B站黑马教程,边看边记。略粗糙,建议视频加笔记

数据类型

基本类型

  • int 整型
  • boolean 布尔型
  • short 短整型
  • long 长整型
  • char 字符型
  • byte 字节型
  • float 单精度浮点型
  • double 双精度浮点型

引用类型

  • String 字符串
  • 数组
  • 接口等等

数据转换

自动类型转换(隐式)

规则:数据范围从小到大,跟字节无关

long num1 = 100 (long数据范围 > int)//100

double num2 = 100F (double > float)//2.5

float num3 = 30L (float > long 虽然long内存占比大于float 但是数据范围float大于long)//30.0

强制类型转换

格式 int num1 = (int) 100L

不推荐使用,会发生数据的溢出或损失

例:

int num2 = (int) 6000000000L //1705032704溢出

int num3 = (int)3.5 //3精度损失

byte/char/short 三种类型都可以发生数学运算

会被先提升为int型,然后进行计算

例:

char str1 = 'A';
System.out.println(str1 + 1); //66 'A'会被先提升为int,值为65,再进行计算。其他同理

根据变量优化,重要的一点是,如果提升以后,要用int接收

例:

short a = 8;
short b = 5;
short res = a+b;//报错,因为此时a、b会被提升为int,需要用int去接收
int res = a+b;

Java当中的内存划分

栈(Stack)

存放的都是方法中的局部变量,有作用域,出域出栈。方法的运行一定要在栈当中

堆(Heap)

存放的都是new出来的东西,例如数组,堆内存里的东西都有一个地址值,16进制。

  • 整数 默认值:0
  • 浮点数 0.0
  • 字符 ‘u\000’
  • 布尔 false

方法区(Method Area)

存储.class相关信息,包含方法的信息

本地方法栈(Native Method Stack)

与操作系统相关

寄存器(pc Register)

与CPU相关,性能特别高

面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。

面向对象的语言中,包含了三大基本特征,即封装继承多态

类和对象

类:一组相关属性和行为的集合

对象:是一类事物的体现,对象是类的实例,对象是实体,类是抽象的

重写和重载

重写(@Override):再继承关系当中,方法的名称一样,参数列表也一样。

重载(Overload):方法的名称一样,参数的列表不一样

public class Fu{
    
    
  public viod method(){
    
    
      
  }
}
public class Zi extends Fu{
    
    
    @Override
    public void method(){
    
    
        
    }
}

子类方法的返回值必须小于等于父类方法的返回值范围。

public class Fu{
    
    
  public viod method(){
    
    
      return null
  }
}
public class Zi extends Fu{
    
    
    public String method(){
    
    
        return null
    }
}
// String 比父类小

子类方法的权限必须大于等于父类方法的权限修饰符

public > protected > (default) > private

example:

public class Phone{
    
    
    public void call(){
    
    
        
    }
    public void send(){
    
    
        
    }
    public void show(){
    
    
      System.out.println("show numbers");    
    }
}

public NewPhone extends Phone{
    
    
    public void show(){
    
    
    // 尽量不要动父方法
      super.show(); 
      System.out.println("show ava");  
      System.out.println("show name");  
      
    }
}

构造方法

子类构造方法当中有一个默认隐含的super()调用,所以一定是先调用的父类构造,后执行子类

子类构造可以通过super调用父类重载构造

public class Fu {
    
    
    public Fu() {
    
    
        
    }
    public Fu(int num) {
    
    
        
    }
}
public Zi extends Fu{
    
    
    public Zi(){
    
    
        //super(); 只能调用一次 不能两个都调用
        super(num : 20);
    }
}

抽象类

抽象方法,就是加上abstract关键字,然后去掉大括号,直接分号结束

public abstract class Animal{
    
    
    // 这是一个抽象方法
    public abstract void eat();
}

抽象类不一定必须有抽象方法

抽象类不能直接创建一个实例,而是用一个子类去继承抽象父类

子类必须覆盖重写抽象定义的所有方法,覆盖重写(实现),子类去掉抽象方法的abstract关键字,然后补上括号并实现

public class Cat extends Animal{
    
    
    @Override
    public void eat(){
    
    
        System.out.println("eat fish");
    }
}

创建子类进行使用

Cat catOne = new Cat();
carOne.eat();

抽象类可以有构造方法,是供子类创建对象的时候,初始化父类成员使用的

public abstract class Fu{
    
    
    public Fu(){
    
    
        System.out.println("fu constractor")
    }
    public abstract void eat();
}

public class Zi extends Fu{
    
    
    public Zi(){
    
    
        System.out.println("Zi constractor")
    }
    @Override
    public void eat(){
    
    
        System.out.println("eat fish");
    }
}

public class Example {
    
    
    public static void main(String[] args){
    
    
        Zi zi = new Zi();
        zi.eat();
        //"fu constractor"
        //"Zi constractor"
        //"eat fish"
    }
}

如果子类不覆盖重写抽象父类的抽象方法,那么子类也必须是一个抽象类

public abstract class Animal{
    
    
    public Animal(){
    
    
        System.out.println("Animal constractor")
    }
    public abstract void eat();
    public abstract void sleep();
}

public abstract class Dog extends Animal{
    
    
// 不加abstract报错,下面没有重写sleep抽象方法,这也是个抽象类,需要孙子类去实现重写
    public Dog(){
    
    
        System.out.println("Dog constractor")
    }
    @Override
    public void eat(){
    
    
        System.out.println("eat meat");
    }
}

public class DogA extends Dog(){
    
    
    @Override
    public void sleep(){
    
    
        System.out.println("hehehehe~");
    }
}

public class DogB extends Dog(){
    
    
    @Override
    public void sleep(){
    
    
        System.out.println("huhuhuhu~");
    }
}

接口

接口就是多个类的公共规范

接口是一种引用数据类型,最重要的内容就是其中的抽象方法

定义

public interface 接口名称{
    // 接口内容
}

换成了关键字interface之后,编译生成的字节码文件仍然是.java->.class

如果是java7 还可以额外包含的内容有:常量 抽象方法

如果是java9 还可以额外包含私有方法

public interface MyInterfaceAbstract{
    
    
    // abstract method
    public abstract void method();
    // public abstract 可省略
}

使用(实现)

public class 实现类名 implements 接口名称{
    
    
    // ...
    // 必须覆盖重写接口(实现)中所有的抽象方法,类似抽象类的抽象方法
}

example:

public interface MyInterfaceAbstract{
    
    
    public abstract void method();
    // default method 默认方法会被实现类继承
    public default void methodDefault(){
    
    
        // 接口的默认方法,可以通过接口实现类对象,直接调用
        // 接口的默认方法,也可以被解耦实现类进行覆盖重写
        System.out.println("interface default method");
    }
}

public class MyInterfaceAbstractImplA implements MyInterfaceAbstract{
    
    
    @Override
    public void method(){
    
    
        System.out.println("override interface");
    }
}

public class MyInterfaceAbstractImplB implements MyInterfaceAbstract{
    
    
    @Override
    public void method(){
    
    
        System.out.println("override interface");
    }
    @Override
    public default void methodDefault(){
    
    
        System.out.println("override interface default method");
    }
}

public class InterfaceTest {
    
    
    public static void main(String[] args){
    
    
        MyInterfaceAbstractImplA a = new MyInterfaceAbstractImplA();
        a.method(); //调用的实现类的方法
        //调用默认方法,如果实现类当时中没有,会向上找接口
        a.methodDefault(); // interface default method
        
        MyInterfaceAbstractImplB b = new MyInterfaceAbstractImplB();
        b.method(); 
        b.methodDefault(); //override interface default method
        
    }
}

接口里定义静态方法

就是将abstract或者default换成static即可,带上方法体

public static 返回值类型 方法名称(参数列表){
    
    
    //方法体
}

public interface MyInterfaceStatic{
    
    
    public static void methodStatic(){
    
    
        System.out.println("this is a static interface method");
    }
}

// Error use  ******

public class InterfaceA implements MyInterfaceStatic{
    
    
    
}

public class Test{
    
    
    public static void main(String[] args){
    
    
        InterfaceA a = new InterfaceA();
        a.methodStatic();
    }
}

// Correct use ******
public class Test{
    
    
    public static void main(String[] args){
    
    
        MyInterfaceStatic.methodStatic();
    }
}

Question:

我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题,但是这个共有方法不应该让实现类使用,应该是私有化的。

解决方案
从java9开始,接口当中允许定义私有方法。

普通私有方法,解决多个默认方法之间重复代码的问题

private 返回值类型 方法名称(参数列表){
    
    
    // 方法体
}

静态私有方法,解决多个静态方法之间重复代码的问题

private static 返回值类型 方法名称(参数列表){
    
    
    // 方法体
}

example:

public interface MyInterfacePrivateA{
    
    
    public default void methodDefault01(){
    
    
        System.out.println("default method A");
        methodCommon();
    }
    public default void methodDefault02(){
    
    
        System.out.println("default method B");
        methodCommon();
    }
    private void methodCommon(){
    
    
        System.out.println("default method AAA");
        System.out.println("default method BBB");
    }
}

public class MyInterfaceAAA implement MyInterfacePrivateA{
    
    
    public void methodAnother(){
    
    
        // methodCommon(); error 访问不到
    }
}

//静态方法同默认方法

Interface 中的成员变量(也就是常量)

必须使用public static final三个关键字进行修饰

public interface MyInterface{
    
    
    // 这其实就是一个常量,一旦赋值,不可以修改,接口中名称使用完全大写用下划线分割
    public static final int NUM = 10;
    // public static final 可以省略
}

Java 9+版本中,接口的内容可以有:

  1. 成员变量其实就是常量,格式[public] [static] [final] 数据类型 = 数据值
  2. 接口中最重要的就是抽象方法,格式 [public] [abstract] 返回值类型 方法名称(参数列表)
  3. 从Java8开始,接口里允许定义默认方法,格式:[public] default 返回值类型 方法名称(参数列表)
  4. 从Java8开始,接口里允许定义静态方法,格式[public] static 返回值类型 方法名称(参数列表)
  5. 从Java9开始,接口里允许定义私有方法,格式:普通私有方法:private 返回值类型 方法名称(参数列表) 静态私有方法 private static 返回值类型 方法名称(参数列表)

一个类的直接父类是唯一的,但是一个类可以同时实现多个接口

public class MyInterfacceImpl implements InterfaceA, InterfaceB{
    
    
    // 覆盖重写所有抽象方法
    @Override
    public void methodA(){
    
    
        // 实现接口A中的抽象方法
    }
    @Override
    public void methodB(){
    
    
        // 实现接口B中的抽象方法
    }
    // 如果两个接口中有相同的抽象方法,只需覆盖重写一次即可
    @Override
    public void method(){
    
    
        // 实现共有抽象方法
    }
    // 如果A跟B中有冲突的默认方法,实现类里面也得覆盖重写
    @Override
    public void methodDefault(){
    
    
        // 实现冲突默认方法
    }
}

多态

面向对象的三大特征:封装性,继承性,多态性。

extends继承或者implements实现,是多态性的前提

代码当中体现多态性,其实就是一句话,父类引用指向子类对象

格式

/**父类名称 对象名 = new 子类名称();
*或者
*接口名称 对象名 = new 实现类名称();
*/
public class Fu{
    
    
    public void method(){
    
    
        System.out.println("i'm a father method");
    }
    public void fuMethod(){
    
    
        System.out.println("i'm a father personal method");
    }
}

public class Zi extends Fu{
    
    
    @Override
    public void method(){
    
    
        System.out.println("i'm a son method");
    }
}

// 多态的写法
public class Test{
    
    
    public static void main(String[] args){
    
    
        // 左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();
        obj.method(); // i'm a son method
        obj.fuMethod(); // i'm a father personal method
    }
}

总结:左父右子就是多态,一只猫被当作动物来看待,也是正确的。这就是多态的特征。

访问成员变量的两种方式:

  1. 直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上找。
  2. 简介通过成员变量访问
public class Fu{
    
    
    int num = 10;
    public void method(){
    
    
        System.out.println("i'm a father method");
    }
    public void fuMethod(){
    
    
        System.out.println("i'm a father personal method");
    }
}

public class Zi extends Fu{
    
    
    int num = 20;
    int zinum = 30;
    @Override
    public void method(){
    
    
        System.out.println("i'm a son method");
    }
}

// 成员变量不能进行覆盖重写

public class Test{
    
    
    public static void main(String[] args){
    
    
        // 左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();
        System.out.println(obj.num) // 10
        System.out.println(obj.zinum) // error 只能向上查找,不能向下查找,左边为父
    }
}

用途举例:

抽象类或接口:Employee 员工

抽象方法: work(); 工作

Employee
work()

有教师和助教两个角色继承Employee或实现Employee接口

Teacher Assistant
work()(讲课) work()(辅导)

如果不使用多态

Teacher one = new Teacher();
one.work();//讲课
Assistant two = new Assistant();
two.work();//辅导

但是现在唯一要做的事就是调用work()方法,其他的功能不关心

如果使用多态

Employee one = new Teacher();
one.work();//讲课
Employee two = new Assistant();
two.work();//辅导

这样的好处是,无论右边new的时候换成哪个子类对象,等号左边调用的方法不会变化。让我们的代码更灵活

对象的向上转型,其实就是多态的写法

注意事项:向上转型一定是安全的,因为是从小范围转向了大范围

但是一旦向上转型以后,就无法调用子类的方法!

为了避免无法调用子类的方法而向下转型

子类名称 对象名 = (子类名称)父类对象

example:

Teacher one = (Teacher) Employee;
// 将父类对象还原成原来的子类对象,但是必须之前是什么子类就得转换成什么子类。

如何才能知道一个父类引用的对象,本来是什么子类。
格式:

对象 instanceof 类名称
//这样对得到一个boolean值结果,也就是判断前面的对象能不能当时做后面类型的实例。

example:

public class Test{
    
    
    public static void main(String[] args){
    
    
        // 。。。
    }
    public void giveAnimal(Animal animal){
    
    
    // 如果不知道animal的类型
        if (animal instanceof Dog){
    
    
            Dog dog = (Dog) animal;
            dog.watchHouse();
        } else{
    
    
            Cat cat = (Cat) animal;
            cat.eatFish();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/ICe_sea753/article/details/114394616