Java基本程序设计结构
- 8种基本数据类型
4种整型:byte、short、int、long
2种浮点:float、double
1中布尔型:boolean
1种字符型:char
注意:java中char描述了UTF16编码中的一个代码单元,占两个字节(所以char不一定能表示一个完整的字符,因为有的字符可能由两个代码单元组成) - java运算符注意
1.&& 和 || 短路求值
2.java中区分逻辑右移动(>>>,高位填充0) 和 算数右移(>>,高位填充符号位) - 字符串注意
1.String 类对象是不可变的,即不能修改字符串中的单个字符(java中字符串不是字符数组)
2.不要使用==判断字符串是否相等(只能判断地址是否相同)=>使用equals
3.空串"" 不等于Null串,空串是一个对象,有自己的长度和内容;Null只是一个没有对象关联的变量
4.用字符串拼接的方式构建字符串效率低=> 使用StringBuilder - 数组
1.数组是对象!!!
2.java数组长度不要求是常量,new int[n]语法正确
3.长度为0的数组与null不同!
4.java中将数组变量直接赋值给另一个数组变量时,两个为变量将引用同一个数组 => 想要实现完全拷贝,使用Arrays类的copyOf方法
5.可以直接声明二维数组,可以构建不规则数组
对象与类
- 访问修饰符
private | 默认 | protected | public | |
---|---|---|---|---|
同类 | √ | √ | √ | √ |
同包 | √ | √ | √ | |
子类 | √ | √ | ||
所有 | √ |
1. 四个访问修饰符都可以控制成员变量和方法; 但只有default和public可以控制类
2. 在X可见表示在X中出现时可正常使用;若对X不可见,即使是拥有方法f的对象O在X中也无法使用它自己的方法
-
非访问修饰符
1.static:修饰的变量和方法属于类而非对象
2.final:修饰的变量不能被修改,方法不能被重写,类不能被继承
3.abstract:修饰的方法没有任何实现,类不能实例化需被继承 -
类之间的关系
1.依赖 => use a
2.聚合 => has a
3.继承 => is a -
对象变量没有实际包含一个变量,它只是引用一个变量
-
不要编写返回可变对象引用的访问器方法,如果真的需要返回对象引用,首先应该进行克隆,否则可能改变原对象!!!
-
静态字段和方法
1.对于static修饰的字段,每个类只有一个这样的字段(System.out就是静态常量)
2.静态方法只可以访问静态字段!静态方法可直接使用类名来调用 -
方法参数
1.理解按值传递和按引用传递
2.java只有按值传递(复制传入的参数,传入对象引用时复制的是引用不是对象!!!)
3.划分的依据不在于传入的是否为地址,在于传入后是否会对数据进行复制 -
对象构造
1.如果没有写构造方法,会自动提供无参构造方法
2.如果写了构造方法,要想使用无参构造方法,需要显示声明
3.构造器初始化过程:=> p131
继承
- 子类中可以通过super访问超类的私有字段
- Java中一个类不能同时继承多个超类,只能通过接口实现
- 多态
1.定义:一个对象变量可以指示多种实际类型
2.仅子类的引用可以赋给超类,但是超类的引用不能赋给子类
3.多态是指方法的多态,属性没有多态!属性看引用类型,方法看对象类型(可参考JVM对应章节)
4.多态存在的三个前提:
a.有继承关系
b.子类重写父类的方法
c.父类引用指向子类对象 => 父类引用调用方法时实际上是子类的方法
注意:上述3的说法是多态的一种,严格来说还包括重载等 - 在覆盖(Override)一个方法的时候,子类方法不能低于超类方法的可见性!!如果超类方法是public,子类方法也必须声明为public
- 强制类型转换
1.只能子类向超类转换
2.可以使用instanceof 检查是否能转换成功 - 抽象类
1.包含一个或者多个抽象方法的类本身必须被声明为抽象的
2.抽象方法不用实现,需在子类中实现
3.抽象类中可包含成员变量以及实现了的方法 - Object类中的一些方法
1.equals:在Object中直接判断两个对象引用(地址)是否相等,若想根据值进行比较,则需要进行重写
2.hashCode:Object的hashCode方法是natice的,由宿主系统实现。Object默认的hashCode方法从对象的存储地址导出; String类重写了hashCode 方法,由字符串的内容导出
3.toString:返回对象的一个字符串,默认输出散列码
… - 自动装箱
1.包装器是不可变的,一旦构造了包装器就不允许更改其中的值(看源码可知因为类中存储基本数据类型的变量是final的),理解如下:
Integer a=3;
a=4; //此时的a已经指向了另一个对象,而不是原来的对象!!!
2.自动装箱:Integer.valueOf(num)
3.自动拆箱:int b=list.get(i); 其中list.get(i)返回一个Integer对象
4.装箱和拆箱是编译器的工作,而不是虚拟机
- 参数数量可变的方法 => eg,传入参数(Object…args)
- 反射
getClass方法
…待细看!!!
接口、Lambda表达式、内部类
- 接口基础
1.接口中的所有方法自动public,不过在实现接口时必须把方法声明为public
2.接口中可以定义常量(自动为public static final),但是不能有实例字段;
3.不能构造接口的对象,但是可以声明接口的变量,接口变量必须引用实现了接口的类对象 - 接口和抽象类
1.可以简单地将接口看成没有实例字段的抽象类
2.一个类只能继承一个(抽象)类,但是可以同时实现多个接口 - 接口与回调
通常将接口类型作为需要回调的方法的形参,运行时传入实现了接口的对象!! - Comparable与Comparator
1.Comparable包含compareTo(T other)方法,在实现了接口的对象自身上调用
2.Comparator包含compare(T first, T second)方法,在比较器对象上调用 - 对象克隆
1.深拷贝与浅拷贝
2.Cloneable接口
3…详见p237 - lambda表达式基础
1.是一个可传递的代码块,可理解为匿名函数
2.回调时传递lambda表达式比传递实现了接口的对象更方便 - 函数式接口
1.定义:对于只有一个抽象方法的接口,需要实现了这种接口的对象时,可以提供一个lambda表达式,这种接口称为函数式接口
2.在低层中,需要回调的函数接收的仍然是实现了接口的某个类的对象,只是将接口中的方法替换为lambda表达式
3.在Java中,lambda表达式能做的也仅仅是转换为函数式接口!甚至不能把lambda表达式赋给类型为Object的 变量!使用lambda表达式必须为其建立一个特定的函数式接口
4.常用Runnable函数式接口 - 闭包
1.定义:一个方法内部将要回调的函数+回调函数之外的自由变量
2.Java中lambda表达式就是闭包
3.lambda表达式能够捕获外围作用域中变量的值,但是这个值必须是事实最终变量,不能修改!!! - 内部类的作用
1.内部类可以对同一个包中的其它类隐藏
2.内部类方法可以访问定义这个类的作用域中的数据,包括原本的私有数据 - 内部类基础
1.内部类的对象总有一个隐式引用,指向创建它的外部类对象
2.内部类是一个编译器现象,与虚拟机无关,编译器会把内部类转换为常规的类文件,用$分隔内部类与外部类名
异常、断言、日志
- 异常分类
非检查型异常:Error类 和 RuntimeException类的异常
检查型异常:所有其他异常 - 抛出异常
1.在方法首部之处方法可能抛出一个异常
2.抛出异常时,方法不会有任何返回值,而是抛出一个封装了错误信息的对象
3.不需要声明非检查型异常(Error和RuntimeException) - 捕获异常
1.捕获异常使用try/catch块
2.通常捕获知道如何处理的异常,继续传播不知道怎么处理的异常
3.finally子句:不管是否有异常被捕获,finally子句中的代码都会被执行 - 断言
…翻书 - 日志
…翻书
泛型
- 泛型基础
1.通常泛型变量使用:E表示集合,K V分别表示键值,T U S 表示任意类型
2.不仅可定义泛型类,还可定义泛型方法
3.类型变量的限定通常使用extends,如< T extends Comparable > - 泛型与虚拟机
1.虚拟机没有泛型类型对象,所有对象都属于普通类
2.类型擦除:无论何时定义一个泛型类型,都会自动提供一个相应的原始类型。这个原始类型的名字就是去掉类型参数后的泛型类型名;类型变量会被擦除,并替换为其限定者(无限定的变量则替换为Object)
杂七杂八
- java实现了多线程(不同的JVM有所不同,有的JVM也是直接使用操作系统的多线程),而C++只能调用操作系统的多线程机制(C11开始引入多线程)
- 关于多线程调用单例对象的同一个方法
多线程调用单例对象的同一个方法,并不需要排队调用
因为:JVM方法调用栈是线程私有的,这就相当于该方法被复制成了多个方法,互不影响