java学习笔记------基础(一)

学习资料:b站尚学堂Java300

目录

手写笔记

对象创建 

关于重写

多态(polymorphism) 

抽象类和抽象方法

接口

String类

内部类


【尚学堂】Java300集零基础适合初学者视频教程_Java300集零基础教程_Java初学入门视频基础巩固教程_Java语言入门到精通_哔哩哔哩_bilibili

主要是记录一些容易混淆或者是比较重要的细节和知识点

先把之前的手写笔记直接拿过来, 再敲一遍太麻烦了

手写笔记

对象创建 

创建对象的四步:

  1. 分配对象空间, 并将对象成员变量初始化为0或空
  2. 执行属性值的显式初始化
  3. 执行构造方法
  4. 返回对象的地址给相关的变量 

静态导入:导入指定类的静态属性和静态方法

import static java.lang.Math.*; //导入Java类的所有静态属性
import static java.lang.Math.PI;  //导入Math类的PI属性

final修饰的变量赋值有三种方式:

  1. 定义时赋值且不可改变
  2. 构造方法中赋值
  3. 类静态代码块中赋值 

静态初始化块, 最先运行, 先于构造方法, 但是程序运行不管创建几个对象都只会运行一次 

    static{
        System.out.println("Initialize the class");
        school = "CCNU";
        showSchool();  //静态初始块内可调用静态方法
    }

 子类创建对象时即使没有调用父类的构造方法, 父类的静态初始化块仍然会运行


子类不继承父类的构造方法但是会调用, 子类的任何构造函数第一行代码如果没有显式调用super(..)或者this(..), 那么java默认都会调用super(), 即调用父类的无参构造方法, 这里的super()可以省略


关于重写

子类重写与重载的区别:

子类的同名方法如果参数列表与父类方法不一致可以看成重载, 返回值类型就可以不同, 如果同名方法的参数列表一致则需要遵循重写相关规则, 返回值类型不可随意变更


子类无法重写父类的静态方法, 当父类为static方法时子类重写也必须是static方法, 这样编译不会报错, 但是实际上也并没有对父类静态方法进行重写, 父类对象为子类对象的向上转型时调用的仍然是父类的静态方法, 而非静态重写函数则在此种情况下调用的是子类的方法

    public void show(){}  //报错,子类无法重写父类同名静态方法
    public static void show() {  //子类同名静态方法会覆盖(不是重写和重载,即子类父类同名方法独立存在,各调用各的)父类静态方法
        System.out.println("Show Student");
    }  //不报错, 但是并没有重写父类方法

重写equals方法

  • 重写equals方法时传入的形参一定是Object类
  • 重写equals方法时一定也要重写hashCode方法, 这样可以避免使用Set和Map时出现问题

重写equals方法时看情况来选择使用instanceof还是getClass()方法, 前者可比较子类, 后者只能同类比较

    public boolean equals(Object o){
        if (this == o) return true;
//        if (o == null || getClass() != o.getClass()) return false;
//        Person person = (Person)o;
//        return id == person.id && name.equals(person.name);
        if (o instanceof Person){
            Person person = (Person)o;
            return person.id == id && person.name == name;
        }
        return false;
    }

Object类的默认toString()方法返回的是类名@地址


多态(polymorphism) 

多态的存在是为了满足程序的灵活性, 有了多态之后就可以用父类一个接口来调用任意个子类的方法, 而不需要对同名方法针对各个子类进行重载, 多态需要满足下面三个条件:

  1. 继承
  2. 方法重写
  3. 父类引用指向子类对象
package com.kiddy.test;

public class Animal {
    static void shout(Animal animal){
        animal.shout();
    }
    void shout(){
        System.out.println("Animal is shouting");
    }

    public static void main(String[] args){
        Animal animal = new Animal();
        Animal tiger = new Tiger();
        Animal lion = new Lion();
        shout(animal);
        shout(tiger);
        shout(lion);
        animal.shout();
        tiger.shout();
        lion.shout();
    }
}

class Lion extends Animal{
    void shout(){
        System.out.println("Lion is shouting");
    }
}

class Tiger extends Animal{
    void shout(){
        System.out.println("Tiger is shouting");
    }
};


抽象类和抽象方法

抽象方法: 使用abstract修饰的方法, 没有方法体只有声明. 定义的是一种规范, 就是告诉子类必须要给抽象方法提供具体的实现

抽象类: 包含(一个以上)抽象方法的类就是抽象类, 通过抽象类就可以做到严格限制子类的设计, 使子类之间更加通用

注:抽象类不能实例化, 不能够new. 抽象类可以包含属性, 方法, 构造方法. 但是构造方法不能用来new实例, 只能用来被子类调用. 

package com.kiddy.test;

public abstract class Move {
    private String name;
    abstract void move();  //抽象方法不能有方法体

    public void setName(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public static void main(String[] args) {
        Move move = new Dog();
        move.move();
    }
}
class Dog extends Move{

    @Override
    void move() {  //父类的抽象方法必须实现
        setName("Dog");
        System.out.println(getName() + " is running");
    }
}


接口

接口是比抽象类还抽象的抽象类, 抽象类还提供某些具体实现, 接口不提供任何实现, 所有方法都是抽象方法. 接口可以更加规范地对子类进行约束, 全面而专业地实现了规范和具体实现的分离. 生产活动中往往使用"面向接口"的思想来设计系统. 接口与实现类不是父子关系, 是实现规则的关系

接口声明格式:

[public] interface Name [extends Father1, Father2...] {

        [public static final] VarType name;  //常量定义

        [public abstract] VarType function();

}

上述格式适用于jdk1.8之前, 之后的版本接口中可以包含普通的静态方法和默认方法

jdk8以后可以在接口中定义默认方法和静态方法

用default修饰的方法就是默认方法, 默认方法需要模板的实现类对象来调用

接口可多继承, interface A extends B, C那么实现类就需要实现ABC里声明的所有方法 

public interface Action {
    void move();

    default void fun1(){
        System.out.println("默认方法");
        fun2();  //接口的默认方法可以调用静态方法
    }

    public static void fun2(){
        System.out.println("接口内静态方法");
    }  //接口内的静态方法
}

interface Eat{
    void eat();
}

class Bird implements Action, Eat{
    @Override
    public void move(){
        System.out.println("Birds fly");
    }
    public static void main(String[] args) {
        Bird bird = new Bird();
        bird.move();
        bird.eat();
//        Eat eat = (Eat)bird;
//        eat.eat();
        bird.fun1();
        Action.fun2();  //直接调用接口的静态方法
        Action a2;  //接口类型的引用是可以的
    }
    @Override
    public void eat() {
        System.out.println("Birds eat");
    }
}

String类

    public static void main(String[] args) {
        String str1 = "abcde";
        String str2 = "abcde";
        String str3 = new String("abcde");
        System.out.println(str1 == str2);  //true
        System.out.println(str1 == str3);  //false
    }

这里str1与str2都指向同一个常量池地址, 而str3的地址则是一个String类对象地址

String类常用操作:

package com.kiddy.test;

public class TestString {

    public static void main(String[] args) {
        String str1 = "abcde";
        String str2 = "ABcDEAB";
        System.out.println(str1.equals(str2));
        System.out.println(str1.equalsIgnoreCase(str2)); //equalsIgnoreCase方法无视大小写比较字符串是否相同
        System.out.println("" + str1.charAt(0) + str1.charAt(str1.length()-1));  //空字符串一定要加在最前面, 不然输出的是数字
        System.out.println(str1.indexOf("bc"));  //从头开始找匹配字符串的位置
        System.out.println("abcdabc".lastIndexOf("abc"));  //  从后往前找匹配子串的位置
        System.out.println(str2.replace("AB", "12"));  //字符串替换
        System.out.println(str2.startsWith("ABC"));  //判断是否以特定字符串开头
        System.out.println(str2.endsWith("AB"));  //判断是否以特定字符串结尾
        System.out.println("01234567".substring(0, 4) + " | " + "01234567".substring(4));  //字符串切片
        System.out.println(str1.toUpperCase());  //全部转大写
        System.out.println(str2.toLowerCase());  //全部转小写
        System.out.println("  12 3  ".trim());  //删除头尾空格
        System.out.println("  12 3  ".trim().replace(" ", ""));  //删除所有空格
    }
}
false
false
ae
1
4
12cDE12
false
true
0123 | 4567
ABCDE
abcdeab
12 3
123

进程已结束,退出代码为 0

内部类

内部类是为了解决封装问题, 使同一个包的类不能直接调用内部类, 而需要通过外部类来访问内部类

内部类可分为成员内部类(静态、非静态)、匿名内部类(一次性使用)、局部内部类

package com.kiddy.test;

/**
 * 测试各种内部类
 */
public class TestInner {
    static{
        System.out.println("*******");
    }
    int a = 0;
    static float b;
    void subtest(A a) {
        Inner2.showInner2();
        a.fun1();
        a.fun2();
    }
    void subtest2(B b){
        b.fun();
    }
    public class Inner{  //非静态内部类不能有static方法和变量
        int a = 3;
        void subtest(){
            System.out.println("Inner.subtest");
        }
        void showInner(){
            System.out.println("Inner.showInner");
            System.out.println(this.a);
            System.out.println(TestInner.this.a);  //访问外部类属性
            subtest();
            TestInner.this.subtest(new A() {  //匿名类继承接口
                @Override
                public void fun1() {
                    System.out.println("Inner.subtest.fun1");
                }

                @Override
                public void fun2() {
                    System.out.println("Inner.subtest.fun2");
                }
            });  //访问外部类方法
            subtest2(new B(){  //匿名类继承父类
                void fun(){  //重写父类方法
                    System.out.println("匿名类的方法");
                }
            });
        }
    }
    static public class Inner2{
        static void showInner2(){
            System.out.println("Inner2.showInner2");
            System.out.println(b);  //静态内部类只能访问外部类的静态成员
        }
    }

    public static void main(String[] args) {
//        TestInner.Inner inner = new TestInner().new Inner();
        Inner inner = new TestInner().new Inner();
        inner.showInner();
    }
}
interface A{
    void fun1();
    void fun2();
}
class B{
    void fun(){
        System.out.println("B的方法");
    }
}

*******
Inner.showInner
3
0
Inner.subtest
Inner2.showInner2
0.0
Inner.subtest.fun1
Inner.subtest.fun2
匿名类的方法

进程已结束,退出代码为 0

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值