实例/对象 Instance/Object
引用 reference
- 引用类型的缺省值是null
- 访问null的属性会报错NullPointerException(NPE)
- Java中的数据类型分为基本数据类型和引用数据类型
引用数据类型和基本数据类型的相同点
- 本身都是一个地址
引用数据类型和基本数据类型的不同点
- 基本类型变量的值,就是地址对应的值。引用数据类型的值还是一个地址,需要通过“二级跳”找到实例
数组
- Java 语言中提供的数组是用来存储固定大小的同类型元素。
- 数组的类名就是类型带上中括号。
- 每个数组对象占用的内存可以不一样
- 数组是相同类型的变量的集合,所有元素的类型都一样。
- 可以指定数组包含的元素个数,最多为int的最大值个
- 元素有固定顺序,每个元素都有索引,从0递增,类型为int
- 数组创建之后,长度不可变
- 数组里每个元素都有初始值,初始值和类型有关。 对于数字类型,初始值是0。对于Boolean类型,初始值是false
- 访问数组过界的错误叫做IndexOutOfBoundException
语法:
数组元素类型[] 变量名 = new 数组元素类型[数组长度]
int[] intArray = new int[9];
String[] strings = new String[2];
intArray[1] = 15; //赋值
intArray[2]; //数组第三个元素
double[] doubleArray = new double[100];
//多维数组
int[][] scores= new int[3][6];
intArray[2][5]; //数组第三个数组中的第六个元素
double[][] scores= new double[5][9];
double[][][] scores= new double[5][9][3];
//这个数组的元素就是二维的double数组,即double[][]
double[][][] double3Array;
int[] a1 = new int[9];
int[] a2 = new int[5];
//数组类名总是以左中括号开头,然后就是不同的标识。
System.out.println(intArray.getClass().getName()); // [I
System.out.println(strings.getClass().getName()); // [Ljava.lang.String;
double[] scores = new double[3];// 不能给数组.length赋值--不能修改数组的长度
int[] intArr1 = new int[5]; //数组
int[][] intArr2 = new int[5][9]; //二维数组
int[][][] intArr3 = new int[5][9][3]; //三维数组...可以建多维数组
//分割线-------------------------
int[] intArr;
intArr = new int[2];
intArr = new int[3]; //相同的引用之间可以互相传值
本质:
- 数组是一块地址连续的内存
- 数组变量[索引]就是在数组原有地址的基础上,加上索引,获得想要的元素
- 所以索引是从0开始的,因为数组变量的地址就是数组第一个元素的地址。
类
- 类名必须和文件名一样,Java程序中不允许类同名
- 类也叫做自定义类型
- 使用new操作符创建类的实例。在Java程序运行的时候,所有这些创建出来的实例都被Java放在堆(heap)中。
在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情形。为了解决这个问题,Java 语言为每一个内置数据类型提供了对应的包装类
类多太混乱?用package管理
为了避免类在一起混乱,可以把类放在文件夹里。这时就需要用package语句告诉Java这个类在哪个package里。package语句要和源文件的目录完全对应,大小写要一致。
- package读作包。一般来说,类都会放在包里,而不会直接放在根目录
- 不同的包里可以有相同名字的类
- 一个类只能有一个package语句,如果由package语句,则必须是类第一行有效代码
import com.phone.parts.Phone //import引入
import com.phone.parts.* // 使用通配符,意思是把parts文件夹下的类都引入
package aa.bb.cc; //必须是有效代码的第一行,意思是此文件在aa文件夹下的bb文件夹下的cc文件夹内
类使用太繁琐怎么办?用import
- 当使用另一个包里的类时,需要带上包名
- 每次都带包名很繁琐,可以使用import语句
属性访问修饰符:public
- 被public修饰的属性,可以被任意包中的类访问
- 没有访问修饰符的属性,称作缺省的访问修饰符,只可以被本包内的其他类和自己的对象使用
- 访问修饰符是一种限制或者允许属性访问的修饰符
类的全限定名
- 包名+类名=类的全限定名。也可以简称为类的全名
- 同一个Java程序中全限定名字不可重复
方法重载(overload)
- 方法签名:方法名+依次参数类型。注意,返回值不属于方法签名。方法签名是一个方法在一个类种的唯一标识。
- 同一个类种方法可以重名,但是签名不可以重复。一个类中如果定义了名字相同,签名不同的方法,就叫做方法的重载。
重载的参数匹配规则
- 方法调用时,参数就不必完全类型一样,对于数字类型的参数,实参数可以自动类型转换成形参类型即可。
- 依照可转换的就近原则:byte,short,int,long,float,double
构造方法---和类名一致并且没有返回值的方法就是构造(constructor)方法。这样Java初始化时会自动调用构造方法。
- 如果类中不存在构造方法,那么Java会默认创建一个参数为空的构造方法。
- 在构造方法里才能调用重载的构造方法。语法为this(参数)
静态变量
- 静态变量使用 static 修饰
- 静态变量如果不赋值,Java也会给它赋以其类型的初始值
- 静态变量在整个Java程序中只有一个(对比实例变量,是每个实例有一份)
- 所以静态变量一旦变化,所有使用这个静态变量的地方的值都会变
- 静态变量一般使用全大写字母加下划线分割。这是一个习惯用法
- 所有的代码都可以使用静态变量,只要根据防范控制符的规范,这个静态变量对其可见即可
- 比如 public 的静态变量,所有的代码都可使用它
- 但是如果没有public修饰符,只能当前包的代码能使用它
public static double DISCOUNT_FOR_VIP=0.95
import aa.bb.cc //cc为静态变量所在的类文件
System.out.println(cc.DISCOUNT_FOR_VIP)
// java 新语法
import static aa.bb.cc.DISCOUNT_FOR_VIP
System.out.println(DISCOUNT_FOR_VIP)
静态方法
- 静态方法(也叫类方法)的特点:只能使用参数和静态变量。换言之,就是没有this自引用的方法
- 静态方法里也可以自己创建对象,或者通过参数,获得对象的引用,进而调用方法和访问成员变量
- 静态方法只是没有this自引用的方法而已。
public static double DISCOUNT_FOR_VIP=0.95
//静态方法使用static修饰符
public static double getVipFun(){
//静态方法可以访问静态变量,包括自己类的静态变量和在访问控制符允许的别的类的静态变量
return DISCOUNT_FOR_VIP
}
static 代码块和 static变量初始化
- 使用某个静态变量的代码块必须在静态变量后面(但是,仅仅赋值没有限制)
- 其实给静态变量赋值也是放在代码块里的,static代码块可以有多个,是从上向下顺序执行的。可以认为这些代码都被组织到了一个clinit方法里(即class init)
- 类加载时,静态代码块就会被统一执行,且静态代码块是顺序执行。所以当方法调用时,静态代码块是已经执行完成了的。
修饰符
- public:全局可见
- 缺省:当前包可见
- private:当前类可见
方法和属性的可见性修饰符
- 可见性修饰符用在类、成员方法、构造方法、静态方法和属性上,其可见性的范围是一样的。
main 方法使用指南
- main 方法也只是一个静态的,有 String[]做参数的,没有返回值的方法而已。它的特殊性在于Java可以把 main 方法作为程序入口。
System 类不简单
- System 类中有很多和系统相关的方法。我们用的最多的就是 in 和 out 来读取和输出数据。
StringBuilder 类
- StringBuilder 是一个非常方便的用来拼接和处理字符串的类,和 String 不同的是,它是可变的。
继承
- 子类继承了父类的方法和属性
- 使用子类的引用可以调用父类的共有方法
- 使用子类的引用可以访问父类的共有属性
-就好像子类的引用可以一物二用,即可以当作父类的引用使用,又可以当作子类的引用使用。
组合
super:和父类对象沟通的桥梁
- 子类对象里可以认为有一个特殊的父类的对象,这个父类对象和子类对象之间通过 super 关键字来沟通。
- 子类中可能会有自定义方法覆盖父类的方法,这是,可以通过super关键字,super.方法名();来访问父级的方法;
父类和子类的引用赋值关系
- 父类引用可以指向子类对象,子类引用不可以指向父类的对象
- 可以进行强制类型转换,如果类型不对,会出错
- 可以调用的方法,是受引用类型决定的
多态
- 静态多态:重载(Overload)
- 动态多态:覆盖()
- 多态的核心问题是:要调用哪个类的哪个方法,这个方法用到的数据(this引用)是谁
instanceof 操作符
protected
final 修饰符最见不得变化
- final 修饰类:不可被继承
- final 修饰方法:不可被子类覆盖
- final 修饰变量:不可被赋值。
万类之祖:Object 类
- 所有的类,都间接或者直接的继承自 Object 类
hashCode 和 equals 方法初探
- hashCode 可以翻译为哈希码,或者散列码。应该是一个表示对象的特征值的 int 整数
- equals 方法应该用来判断两个对象从逻辑上是否相等
toString方法
初探 Class 类
- Class 类是代表类的类。每个Class类的实例都代表了一个类
- 无论时内部类还是匿名类,类都是只有一个,对象可以有多个。不会在每次执行到内部类声明的地方,就创建一个新的类。
初探反射
- 反射(reflection)访问属性
- 反射访问方法
- 反射访问静态方法和属性
- 反射访问 private 的方法和属性
面向对象的三要素:封装、继承、多态
- 封装解决了什么问题,带来了什么问题?
- 继承解决了什么问题,带来了什么问题?
- 多态解决了什么问题,带来了什么问题?
有方法代码的接口
- 在 Java8中,接口中允许有静态方法,私有方法和带有缺省实现的抽象方法
匿名类
- 匿名类是用来创建接口或者抽象类的实例的
- 匿名类是一种创建接口和抽象类对象的语法,任何可疑 new 一个对象的地方,都可以使用匿名类
- 匿名类只能实现/继承一个接口/抽象类,本身没有名字
- 如果是在成员方法或者给成员方法赋值时创建匿名类,那么会有对外部对象的 this 自引用
- 匿名类也可以访问外部类的 private 属性
特殊类的总结
枚举
- 枚举就是有固定个数实例的类
- 枚举的父类是Enum
非公有类
- 最不特殊的类,可以认为就是被缺省访问控制符修饰的类。也就是说,和 public class 的区别仅仅是可以被访问的范围不一样
- 如果一个文件只有非公有类,那么类名和文件名可以不一样。当然文件后缀必须是Java
内部类
- 内部类的特殊之处在于可见性和可以访问的数据以及方法。内部类会被认为是类本身的代码,所以外部类的 private 成员对齐可见。
- 类里面可以有静态变量,成员变量和局部变量,对比着看,内部类也分为这三种。这些内部类的访问修饰符,可以访问的数据以及可见性都可以对比着记忆
静态内部类:可以有访问修饰符,可以在类外部访问(对比静态变量)
成员内部类:可有访问修饰符,有外部类对象的 this 自引用(对比成员方法),可以在外部使用,但是创建对象语法需要指明外部对象
局部内部类:没有访问修饰符(对比局部变量),有外部类的引用,访问参数和局部变量,必须是 final 的
- 内部类可以有父类,可以实现接口