1.java基础-面向对象
三大特性:封装,继承,多态
封装:使用抽象数据类型将数据及其操作封装起来,外界通过对象提供给外界的接口来访问该对象
继承:从父类中获取非private的方法
多态:三大条件(继承,覆盖/重写,向上转型),使用父类调用方法时会实际调用子类重写后的方法
注:向上转型存在于继承和多态中(因为多态用到继承),父类引用指向子类对象(使用父类的类型实例化一个子类的对象)
关系:
泛化关系:描述继承 extends
实现关系:实现接口 implement
聚合关系:整体没了部分还在,不是强依赖
组合关系:整体没了部分也没,强依赖
(理解:公司黄了部门没了-组合;公司黄了我还在-聚合)
关联关系:静态关系,一对一,一对多,多对多等
依赖关系:运行过程中起作用。B类用到A类的东西,可以是方法,参数以及A向B传递的参数
2.java基础-知识点
数据类型
包装类型
基本数据类型:Boolean/1,byte/8,char/16,short/15,int/32,float/32,long/64,double/64
基本数据类型都有对应的包装类型
装箱和拆箱
Integer x = 2;
int y = x;
(就是java中基本数据类型跟包装类型之间的自动转换)
基本类型----->包装类型(自动装箱)
包装类型----->基本类型(自动拆箱)
装箱(valueOf(xxx))跟拆箱(xxx.intValue())
缓存池
缓存池中有一定范围内的对象可以直接取用
new Interger(123)会创建新对象,多次调用会产生多个新对象
Integer.valueOf(123)直接使用缓存池中的对象,多次调用使用的是同一个缓存池对象(超过缓存池范围会创建新的对象)
对应缓存池范围:
boolean values true and false
all byte values
short values between -128 and 127
int values between -128 and 127
char in the range \u0000 to \u007F
String
hash值:文件的身份证,文件更改hash值也会变化
String不可变,hash值也不变
好处:
可以缓存hash值
String Pool(字符串常量池)的需要
安全性
线程安全
String,StringBuffer,StringBuilder区别
只有string不可变;
string因为不可变所以线程安全;只有StringBuilder线程不安全;StringBuffer内部使用synchronize(v.使同步)进行同步,线程安全
String.intern()
作用:保证相同内容的字符串变量引用同一个内存对象
示例:
String n1 = new String("aaa");
String n2 = new String("bbb");
System.out.println(n1==n2);//false
//n1.intern()将n1对象放入String Pool中,返回该对象的引用给n3.故n3与n1指向字符串常量池中的该对象
String n3 = n1.intern();
System.out.println(n1.intern()==n3);//true
//下列方式创建字符串实例时会自动将新建的对象放入String Pool中
String n4 = "cccc";
//n5直接指向了常量池中已经存在的"cccc"
String n5 = "cccc";
System.out.println(n4==n5);//true
运算
参数传递
按值调用:方法接收的是调用者提供的值
按引用调用:方法接收的是调用者提供的变量地址
注:java中只有按值调用
改变对象的内容必须要改变该对象所在内存空间里的字段,所以必须要用到指向该对象地址空间的指针
Animal cat = new Animal();//cat里存的就是指向该对象内存空间的地址。该内存空间中含有与cat有关的字段
访问器与修改器(get与set方法)
如果该类中含有set方法即修改器,则可以通过cat对象调用set方法对内存空间中关于cat的字段进行修改
get方法只能访问不能进行修改
float与double
向下转型:高精度数转为低精度
java中不能隐式执行向下转型
+=运算符可以实现隐式类型转换
short num1 = 1;
num1 += 1;//作用等同于下一句的强制类型转换
num1 = (short) (num1+1);
switch:不支持long类型的对象,设计初衷针对值比较简单的判断
继承
访问权限
java访问权限修饰符:public,private,protected;不加表示包级可见
子类方法中重写了父类方法,要保证子类中该方法访问级别不能低于父类的访问级别。确保能访问父类实例的地方都能使用子类实例。
里氏替换原则
子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。
子类中可以增加自己特有的方法。
当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
抽象类与接口
关系
is-a关系(继承):继承过程中,仅仅是覆盖了父类中的方法
is-like-a关系:有新增的方法
has-a关系(合成,组合):一部分
比较
抽象类提供了一种is-a关系,子类对象必须能够替换掉所有父类对象。接口并不要求接口与实现接口的类有is-a关系。
一个类可以实现多个接口但是不能继承多个抽象类。
接口的字段只能是final,static类型的;抽象类的字段无限制
接口的成员只能是public的,抽象类的成员可以有多个访问权限
使用接口
需要让不相关的类都实现一个方法
需要使用多重继承
使用抽象类
需要在几个相关的类中共享代码
需要能控制继承来的成员的访问权限,而不是都为public
需要继承非静态和非常量字段
java8之后接口可以有默认方法的实现,修改接口的成本变低。接口类一般优于抽象类:接口类没有抽象类严格的类层次结构要求,可以灵活的为一个类添加行为
super()
访问父类的构造函数:使用该函数委托父类完成一些初始化的工作
访问父类的成员:子类中重写了父类中某个方法的实现,可以使用super关键字来引用父类的方法实现
重写与重载
重写
子类实现父类已经实现过的方法
注解@Override:告诉编译器检查重写后的方法是否满足以下原则(即重写的限制)
子类方法的访问权限必须大于等于父类方法
子类方法的返回值必须是父类方法返回值或为其子类型
重载
名称与父类相同但是参数类型、个数、顺序至少有一个不相同
返回值不同,其他都相同不算是重载
重写与重载区别
重载是定义相同的方法名,参数不同,重写是子类重写父类的方法;
重载是在一个类中,重写是子类与父类之间;
重载是编译时的多态性,重写是运行时的多态性。
Object通用方法
概览
equals()
equals()与==
对于基本类型,==判断两个值是否相等,基本类型没有equals()方法
对于引用类型,==判断两个变量是否引用同一个对象,而equals()判断引用的对象是否等价
hashcode()
hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。
等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。
在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。
注:HashSet类,是存在于java.util包中的类。同时也被称为集合,该容器中只能存储不重复的对象(判断方式是散列值不同)。
toString()
默认返回 类名@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示
clone()
clone()是Object的 protected 方法,它不是public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的clone()方法
注意:clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。
浅拷贝:拷贝对象和原始对象的引用类型引用同一个对象(类似:两个指针指向一片内存空间)
深拷贝:拷贝对象和原始对象的引用类型引用不同对象(类似:两个指针指向不同内存空间,两内存空间存储的数据相同)
clone() 的替代方案
使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。
关键字
final
声明方法不能被子类重写
private方法隐式的被指定为final,如果子类中定义的方法和基类中的一个private方法签名相同,此时子类不是重写而是定义了一个新的方法
声明类不允许被继承
static
静态变量
静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存在一份。
实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死
静态方法
静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法(abstract)。
只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字。
静态语句块
静态语句块在类初始化时运行一次
静态内部类
非静态内部类依赖于外部类(外面那一层类)的实例,而静态内部类不需要(非静态内部类实例化时new前面需要外面一层类的实例)
静态内部类不能访问外部类的非静态的变量和方法
静态导包
在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低
初始化顺序
静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序,最后才是构造函数的初始化
存在继承的情况下,初始化顺序为:
父类(静态变量、静态语句块)
子类(静态变量、静态语句块)
父类(实例变量、普通语句块)
父类(构造函数)
子类(实例变量、普通语句块)
子类(构造函数)
反射
通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件)
通过反射机制可以操作代码片段(class文件)
java.lang.Class 代表整个字节码。代表一个类型,代表整个类。
java.lang.reflect.Method 代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor 代表字节码中的构造方法字节码。代表类中的构造方法。
java.lang.reflect.Field 代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)
异常
Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: Error 和 Exception
Error 用来表示 JVM 无法处理的错误
Exception 分为两种
受检异常 : 需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复;
非受检异常 : 是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序崩溃并且无法恢复
泛型
注解annotation
Java 注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用
java与c++的区别
java 是纯粹的面向对象语言,所有的对象都继承自 java.lang.Object,C++ 为了兼容 C 即支持面向对象也支持面向过程。
Java 通过虚拟机从而实现跨平台特性,但是 C++ 依赖于特定的平台。
Java 没有指针,它的引用可以理解为安全指针,而 C++ 具有和 C 一样的指针。
Java 支持自动垃圾回收,而 C++ 需要手动回收。
Java 不支持多重继承,只能通过实现多个接口来达到相同目的,而 C++ 支持多重继承。
Java 不支持操作符重载,虽然可以对两个 String 对象支持加法运算,但是这是语言内置支持的操作,不属于操作符重载,而 C++ 可以。
Java 的 goto 是保留字,不可用,C++ 可以使用 goto。
Java 不支持条件编译,C++ 通过 #ifdef #ifndef 等预处理命令从而实现条件编译