2023.1.10 今年26岁了 深感对未来之恐惧
数据被保护在类的内部,尽可能隐藏内部的细节,只有一些对外接口来与外部发生联系
public class Person {
private String name;
private int gender;
private int age;
public String getName() {
return name;
}
public String getGender() {
return gender == 0 ? "man" : "woman";
}
public void work() {
if (18 <= age && age <= 50) {
System.out.println(name + " is working very hard!");
} else {
System.out.println(name + " can't work any more!");
}
}
}
一个类可以继承自一个父类 获得非private的属性和方法 (public protected)
private protected public 不加访问修饰符 表示包级可见
可以对类或者类中的成员(字段以及方法)加上访问修饰符
** 在类的内部提供接口来访问类的成员
1、抽象类
抽象类和抽象方法使用abstract关键字进行声明。抽象类一般会包含抽象方法,抽象方法一定位于抽象类中
抽象类的特点:不能被实例化,只能先继承抽象类然后实例化
public abstract class classA {
private int y;
public abstract void func1();
public void func2() {
System.out.println("func2");
}
}
class sampleClass extends classA{
@Override
public void func1() {
System.out.println("func1");
}
}
2、接口
接口的成员默认都是public的 并且不允许定义为private protected
public interface Interface {
void func1();
default void func2() {
System.out.println("func2");
}
int x = 123;
public int z = 0;
}
public class InterfaceImpl implements Interface{
@Override
public void func1() {
System.out.println("func1")
}
}
3、比较
4、用法
使用接口:
使用抽象类
public class Father {
protected int x;
protected int y;
public Father(int x, int y) {
// 构造函数
this.x = x;
this.y = y;
}
public void func() {
System.out.println("Father.func");
}
}
子类:
public class Son extends Father {
private int z;
public Son(int x, int y, int z) {
super(x,y);
this.z = z;
}
@Override
public void func() {
super.func();
System.out.println("Son.func()");
}
}
主函数:
public class main {
public static void main(String[] args) {
Father father = new Father(1,2);
Son son = new Son(3,4,5);
father.func();
son.func();
}
}
1、重写 Override
子类实现一个声明和父类相同的方法,需要满足里氏替换原则
2、重载 Overload
存在于同一个类中 方法名与已经存在的方法名相同 但参数类型 个数 顺序至少一个不同
编译时多态:方法重载
运行时多态:程序中定义的对象引用所指向的具体类型在运行期间才确定(比如泛型)
public class Instrument {
public void play() {
System.out.println("Instrument is playing...");
}
}
public class Wind extends Instrument {
public void play() {
System.out.println("Wind is playing...");
}
}
public class Percussion extends Instrument {
public void play() {
System.out.println("Percussion is playing...");
}
}
public class Music {
public static void main(String[] args) {
List<Instrument> instruments = new ArrayList<>();
instruments.add(new Wind());
instruments.add(new Percussion());
for(Instrument instrument : instruments) {
instrument.play();
}
}
}
上面的代码 从静态上看 Instument对象应该调用的是自己的play方法 其实运行中调用的是子类的静态方法
(1)基本类型
基本类型共8个:
boolean/1
byte/8
char/16
short/16
int/32
float/32
long/64
double/64
new Integer(1) — 创建新对象
Integer.valueOf(1) ---- 使用缓存池 得到同一个对象的引用
缓存池大小为-128 ~ 127 (java8)
在这个范围内 使用自动装箱将自动调用valueOf方法
Integer m = 123;
Integer n = 123;
System.out.println(m == n); // true
(2)String
String是不可变的:这句话经常看到,是什么意思呢?
String内部使用char数组来存储数据 并且声明为final,且String内部不提供改变value数组的方法
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
不可变有什么好处:
1、缓存hash值
String类型的hash值不变
2、String pool
如果一个String对象被创建过了 就可以直接从String pool中引用
3、安全性
String是最常用作参数的类型 不可变性保证了传输过程中的安全
4、线程安全
String可以在多个线程中安全使用
StringBuilder可变 非线程安全
StringBuffer可变 且线程安全
String.intern()
intern()方法保证两个变量引用的是同一个对象
String s1 = new String("aaa");
String s2 = new String("aaa");
System.out.println(s1 == s2); // false
String s3 = s1.intern();
System.out.println(s1.intern() == s3); // true
如果使用String s1 = “aaa” 则它已经自动被加入到了String pool中
将参数传入一个方法时,本质是传入了对象的地址
因此在方法中,改变指针引用的对象也将指向另一个完全不同的对象
如果在方法中改变对象的字段/属性,则会发生变化
1.1 这个字面量是double类型 因此直接赋给float是错的
1.1f才是float型
字面量1是int类型,比short的精度更高,因此不能隐式地将int下转为short类型
但是在使用+=时,可以进行隐式转换
条件判断语句的基本写法
String s = "a";
switch (s) {
case "a":
do....
break;
case "b":
do....
break
default:
break;
}
自反性 对称性 传递性 一致性
equals和== 对于基本类型 ==判断两个值是否相等,基本类型没有equals方法
对于引用类型 == 判断两个变量的引用是否是同一个对象 equals判断是否等价
实现上 需要判断每个关键域是否相等 以及对Object转型
返回散列值
默认返回ToStringExample@4554617c这种格式
1、cloneable
clone()是Object的protected方法 如果一个类不显示重写clone() 其他类就不能直接调用该实例的clone()
重写了clone方法后 还需要实现cloneable接口才能够使用
2、浅拷贝
拷贝对象和原始对象的引用类型引用的是同一个对象
3、深拷贝
引用非同一个对象 需要自己实现
使用clone()有很多风险 更好的实践是通过拷贝构造函数或者拷贝工厂来实现
1、数据
声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量
2、方法
声明方法表示不能被子类重写
private方法隐式被指定为final 如果在子类中定义的方法和基类中的一个private方法签名相同 此时子类的方法不是重写基类方法 而是在子类中定义了一个新方法
3、类
声明类不允许被继承
1、静态变量
2、静态方法
静态方法在类加载时就存在,它不能是抽象方法
注意:静态方法只能访问所属类的静态字段和静态方法,且不能有this和super关键字
3、静态语句块
静态语句块在类初始化时运行一次
4、静态内部类
非静态内部类依赖于外部类的实例,而静态内部类不需要
注意:初始化阶段 静态变量、静态语句块优先于实例变量和普通语句块
每个类都有一个Class对象,编译一个新类时,会产生一个同名的.class文件
Class和java.lang.reflect一起对反射提供了支持,java.lang.reflect类库主要包含一下三个类:
Throwable可以用来表示任何可以作为异常抛出的分类,分为Error和Exception
其中Error用来表示JVM无法处理的错误
Exception分为两种:
1、受检异常:需要用try…catch…语句捕获并进行处理,并且可以从异常中恢复
2、非受检异常:例如除以0,此时无法恢复
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
}
java注解是附加在代码中的一些元信息,用于一些工具在编译运行时解析和使用,起到说明、配置的功能。