Java基础知识学习笔记

static、final、abstract、transient关键字

static关键字

  1. static修饰的变量和方法不依赖于类的具体实例,所有类实例共享 同一个static的变量与方法
  2. static方法不能调用非静态的成员变量。但是非静态方法可以调用静态变量

final关键字

指“最终的”,可以修饰类、方法、变量

  1. final修饰的类不能被继承
  2. final修饰的方法不能被子类重写
  3. final修饰的变量被赋值之后不能再修改

abstract关键字

抽象的,可以修饰类、方法

  1. 抽象类:该类不能被实例化,往往是被子类继承,有构造器,便于子类实例化。
  2. 子类继承抽象类,必须实现抽象类中所有的抽象方法才能被实例化。如果没有实现所有的抽象方法,那么该子类也还是一个抽象类,需要用abstract修饰
  3. 抽象方法:只有声明,没有方法体
  4. 有抽象方法的类一定是抽象类,抽象类不一定有抽象方法

abstract不能用来修饰属性、构造器、静态方法、final方法、私有方法

抽象类跟普通类差不多,抽象类多定义了抽象方法。除了不能被实例化之外,并没有任何不同

transient关键字

transient是短暂、瞬变的意思。如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说,用transient关键字标记的成员变量不参与序列化过程。

  1. 序列化

    将对象转换成以字节序列的形式来表示,包含了对象的数据和信息,序列化后可以存在数据库或文件中,也可用于网络传输。序列化之后保存在数据库或文件中,然后反序列化,就会恢复成原来的 Java 对象。

  2. transient关键字的作用

    在某些情况我们不希望对象被序列化(比如用户的密码、银行卡号),那么可以使用关键字transient关掉对象的序列化,被transient修饰的对象不会被序列化。 注意:static修饰的静态变量本身就是不可被序列化的。

  3. transient只能修饰变量,不能修饰方法和类

对象被transient修饰,进行序列化保存在数据库或文件后,再被反序列化时,取到的是 null


重写、重载

重写:主要是指父类与子类之间,子类重写父类的方法,该方法名相同,参数也相同。final修饰的方法不能被子类重写

重载:可以发生在同一个类中、或子类中,方法名相同,参数个数或类型不同,可以造成重载


抽象类

抽象类不能创建类的实例对象,往往用abstract修饰。抽象类里面可以包含抽象方法和非抽象方法。抽象方法只是一个声明,没有具体的函数。

// 抽象类
public abstract class Animal {
	public void jump(){
		System.out.println("我喜欢跳");
	}
	
	public abstract void eat();
}

// 子类是具体类
public class Dog extends Animal{

    @Override
    public void eat() {
        System.out.println("狗狗爱吃肉");
    }
}

// 在主函数中
public static void main(String[] args) {
	// 多态
    Animal a = new Dog();
    
    a.jump();
    a.eat();
}

抽象的小问题

A:抽象类有构造方法,不能实例化,那么构造方法有什么用?

用于子类访问父类数据的初始化

B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?

为了不让创建对象

C:abstract不能和哪些关键字共存

a:final 冲突

b:private 冲突

c:static 无意义

抽象类与接口

  1. 抽象类是对一类具有共性的东西的抽象,接口主要是对动作、操作的描述
  2. 只能单继承,所以抽象类更复杂,需要设计、考虑其子类可能的所有共性;可以实现多个接口,所以更灵活,局限性相对小
  3. 接口实际上是抽象类的变种,接口中的所有方法都是抽象的方法
  4. 接口不允许有方法体,但是抽象类中的方法可以有方法体
  5. 抽象类、接口都不能被实例化,只能被继承使用

注解的种类

内置注解、自定义注解、元注解

常用内置注解

  • @Override 修饰方法,覆盖了父方法
  • @Deprecated 该方法、类、变量等不推荐使用,会有一个删除线
  • @SuppressWarnings 关闭不当的编译器警告信息

元注解,描述其他注解类型

自定义注解
@interface

//自定义的注解
public @interface MyAnnotation {
	String value() default "hello";
}

equals

equals与==的区别

  1. 对于基本类型只能用==,比较值是否相等
  2. String一般使用equals比较值是否相等,==比较内存地址是否相等
  3. 有些不能使用equals比较是否相等,比如StringBuffer。如果想要实现功能需要重写equals方法

String重写的equals方法:

public boolean equals(Object anObject) {
    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;
}

重写equals的要点、equals方法的性质

  1. 自反性:如果x不空,则x.equals(x)为true
  2. 对称性:x,y都不空,则x.equals(y)为true时,y.eqauls(x)也为true
  3. 传递性x.equals(y)y.equals(z)都为true时,z.equals(x)也为true
  4. 一致性:若x,y引用对象没有发生改变,则反复调用x.equals(y)都为相同的结果

String类

String类为什么不可以改变?

private final char value[];

String底层实际上是final的char[]字符数组,数组长度一旦给定就不能改变,所以String不能改变。以下的改变,是指改变了引用内存的指向。sa指向新的内存区域了。

String sa = "abc";
sa += "d";
System.out.println(sa); // abcd

String所谓的不能改变是指,不能在原有的String上做改变,它是new一个新的数组,再复制上去。而StringBuffer是在原有基础上进行修改。

如果想要改变String类,可以用什么方法?

反射。但尽量不要这样使用,会破坏String的不可变性的

String sa = "Hello World";
// 获取value变量
Field valueField = String.class.getDeclaredField("value");
// 因为value是private,需要设置value为可以更改的
valueField.setAccessible(true);
// 获取sa这个对象,转换为char[]类型
char[] valueChar = (char[]) valueField.get(sa);
// 修改值
valueChar[5] = '_';
// 输出 Hello_World
System.out.println(sa);

堆和栈

栈:是内存区域,存储局部变量。凡是定义在方法中的都是局部变量,方法先进栈,变量再进栈。变量用完就会被释放,栈内存更新速度很快,所以局部变量生命周期很短。

堆:存储数组和对象,存储的都是实体。如果数据消失,不代表实体也会消失,所以堆是不会随时释放的。


多态

1. 普通类多态

描述一个事务的多种形态,必须要有父、子类。多态中,父类引用变量调用方法时,会调用子类重写后的方法(向上转型)。如果要使用子类中特有的方法,需要将引用转化为子类类型

public class Test {
    public static void main(String[] args) {
        A a = new B();
        // 父类型对象调用jump方法为子类重写的方法
        a.jump();
        // 调用子类的特有方法,需要强制转换
        B b = (B) a;
        b.run();
    }
}

class A {
    public void jump() {
        System.out.println("class A jump");
    }
}

class B extends A {
    public void jump() {
        System.out.println("class B jump");
    }

    public void run() {
        System.out.println("class B run");
    }
}

2. 抽象类多态

abstract class A {...}
class B extends A {...}
A a = new B();

3. 接口多态

需要明确一点,Java中有单继承的局限,但是可以实现多个接口,可以使用多个相关或者不相关的接口对功能进行扩充,因此,接口更加灵活。接口的实现也具有多态性(子类可以重写接口中的方法;多个子类中同名方法包含的功能不一样)。

interface A {...}
class B implements A {...}
A a = new B();

4. 构造器多态

子类继承父类会重写或重载父类的构造器,此时也会形成多态。要注意初始化顺序与销毁清理的顺序。

4.1. 初始化顺序

​ 子类加载必须先加载父类的构造器,因此初始化顺序为:基类先构造加载,然后再按照继承顺序逐步向下初始化。

4.2. 销毁清理顺序

​ 清理顺序与初始化顺序相反。由于子类的销毁方法中可能会调用父类中的方法,因此销毁要从子类开始。所以销毁顺序为:子类先进行清理,然后按照继承顺序向上调用销毁方法,最后调用基类的方法。


注意:static静态方法、final方法(private是final方法)不具有多态性


正则表达式

1. 字符匹配

  1. 匹配单个任意字符 .。比如:可以匹配bed, b^d, b9d, 但是不能匹配beed.

  2. []匹配中括号中的单个字符。m[abcd]q可以匹配maq,mdq,但是不能mabq,mhq.

  3. |,相当于,匹配指定的单个字符。m(a|b|d|wx)q可以匹配mwxq,mbq, 但不能匹配madq.

  4. [^]表示否定[^x]表示不能是x字符

  5. ^匹配字符串开始的位置

2. 次数匹配

  1. 表示次数
符号含义
*0次或多次
+1次或多次
?0次或1次
{n}刚好n次
{n,m}n到m次
  1. \S非空字符

  2. \s空字符,表示[\t\n\r\f]可以匹配一个空格、制表符、回车符、换页符。不能匹配自己输入的多个空格.

  3. \r空格符

3. 数字匹配

\d表示[0-9]

\w表示[0-9A-Za-z]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值