JAVA学习笔记二
五、继承、接口和抽象类
继承extends
父类/基类/超类
parent/base/super
子类/派生类
child/derived
子类不可访问父类private成员
同名方法优先调用子类
单根继承(区别于C++):每个类只能继承一个类
默认继承java.lang.Object(所有类构成类型继承树),Object类默认有clone,equals,finalize,getClass,hashCode,toString等方法
默认super(),只有一个super(),调用父类的构造函数
抽象类和接口
类:属性(0或多个)+方法(0或多个)
一个完整的类:所有的方法都有实现(方法体)
抽象类:暂时有方法未实现
抽象类组成(类名前加abstract class):
- (optional)成员变量
- (optional)具体方法,方法有实现
- (optional)抽象方法,加abstract关键字
子类必须实现父类抽象类所有的abstract方法才能成为完整类!
接口类interface:所有方法均未实现
P.s.方法不需要加abstract
一个类只可以继承(extends)一个类,但是可以实现(implements)多个接口,继承和实现可以同时。
P.s.弥补单根继承的不足
接口可以继承多个接口,没有实现的方法将会叠加。
没有全部实现方法,就是抽象类。
接口里可以定义变量,一般为常量(final)。
P.s.先extends后implements
抽象类和接口相同点:
- 两者都不能被实例化,不能new操作
P.s.抽象类可new,但是new时需要补全,只可以使用一次
抽象类和接口不同点:
- 抽象类可以有部分方法实现,接口所有方法不能有实现
- 一个类只能继承(extends)一个(抽象)类,实现(implements)多个接口
- 接口可以继承(extends)多个接口
- 抽象类有构造函数,接口没有构造函数
- 抽象类可以有main,也能运行,接口没有main函数
- 抽象类方法可以有private/protected, 接口方法都是public
转型、多态和契约设计
类转型
1.变量支持互相转化
2.子类可以转换成父类(向上转型),而父类不可以转换为子类(向下转型)
E.g.
Human obj1=new Man();
Man obj2=new Human(); //illegal,Man is a derived class Human
父类转为子类有一种情况例外
-就是父类本身就是从子类转化过来的。
E.g.
Human obj1=new Man();
Man obj2=(Man)obj1;
多态
重写(overwrite/override,not overload!):子类继承父类的所有方法,但子类可以重新定义一个名字、参数和父类一样的方法
P.s.overload重载:形参不同
P.s.子类的方法的优先级高于父类。子类转换父类后,会优先调用子类的方法(理解为被掩盖却依旧存在)!
多态的作用:
- 以统一的接口来操纵某一类中不同的对象的动态行为
- 对象之间的解耦
E.g.父类[i]=子类实例0
父类[i].f()==子类.f()
契约设计
契约:规定规范对象应该包含的行为方法
接口定义了方法的名称、参数和返回值,规范了派生类的行为
基于接口,利用转型和多态,不影响真正方法的调用,成功地将调用类和被调用类解耦(decoupling)
契约设计:类不会直接使用另外一个类,而是采用接口的形式,外部可以“空投”这个接口下的任意子类对象
六、static、final和常量设计
static
变量 方法 类 匿名代码块
静态变量,类公有成员?
依赖类存在,不依赖类实例存在
P.s.可用类.静态变量访问
static方法
- 静态方法也无需通过对象来引用,而通过类名可以直
接引用。 - 在静态方法中,只能使用静态变量,不能使用非静态
变量。 - 静态方法禁止引用非静态方法。
P.s.main前加static原因
用static修饰的方法,无须产生类的实例对象就可以调用该方法。
static块
- 只在类第一次被加载时调用,只运行一次。
- 执行顺序:static块 > 匿名块 > 构造函数。
static{
…
}
{
…
}
单例模式(单态模式)singleton
单例模式:保证一个类有且只有一个对象
- 采用static 来共享对象实例
- 采用private 构造函数,防止外界new操作
final
Java的final关键字同样可以用来修饰 类、方法、字段
- final的类,不能被继承
- 父类中如果有final的方法,子类中不能改写此方法
final的变量,不能再次赋值。
- 如果是基本型别的变量,不能修改其值
- 如果是对象实例,那么不能修改其指针(但是可以修改对象内部的值)
常量设计和常量池
常量设计
与C/C++不同,Java无constant关键字
public static final
- 不能修改,final
- 不会修改/只读/只要一份,static
- 方便访问public
P.s.建议变量名字全大写,以连字符相连,如UPPER_BOUND
一种特殊的常量:接口内定义的变量默认是常量
常量池 Constant Pool
常量池:相同的值只存储一份,节省内存,共享访问
Java为很多基本类型的包装类/字符串常量都建立常量池
基本类型的包装类
- Boolean,Byte,Short,Integer,Long,Character,Float,Double
- Boolean: true, false
- Byte:-128~127, Character : \u0000–\u007f (0—127)
- Short, Int, Long:-128~127
- Float,Double:没有缓存(常量池)
基本类型的包装类和字符串有两种创建方式:
常量式(字面量)赋值创建,放在栈内存 (将被常量化,栈内存)
Integer a = 10;
String b = “abc”;
new对象进行创建,放在堆内存 (不会常量化,堆内存)
Integer c = new Integer(10);
String d = new String(“abc”);
这两种创建方式导致创建的对象存放的位置不同
自动装箱 自动拆箱
不可变对象和字符串
不可变对象 Immutable Object
一旦创建,这个对象(状态/值)不能被更改了,内在的成员变量的值就不能修改了。
典型的不可变对象
-八个基本型别的包装类的对象
-String,BigInteger和BigDecimal等的对象
不可变对象传指针(引用)
由于不可变,临时对象指向新内存,外部实参的指针不改动
输出结果:
abc
abc
abc
如何创建不可变对象
-immutable对象是不可改变,有改变,请clone/new一个对
象进行修改
-所有的属性都是final和private的
-不提供setter方法
-类是final的,或者所有的方法都是final
-类中包含mutable对象,那么返回拷贝需要深度clone
不可变对象的优点
-只读,线程安全
-并发读,提高性能
-可以重复使用
缺点
-制造垃圾,浪费空间
可变对象Mutable Object
普通对象
字符串
String定义方法:
-常量赋值
-new对象,堆分配内存
字符串内容比较:equals方法
是否指向同一个对象:指针比较==
//字符串加法
String a=“abc”;
a = a+“def”;
内存会产生abc以及abcdef,a指向后者,效率差
建议 append方法:
-StringBuffer(同步,线程安全,修改快速),
-StringBuilder(不同步,线程不安全,修改更快)
总结
-不可变对象提高读效率
-不可变对象设计的方法
-字符串append操作速度:StringBuilder>StringBuffer>String
第七章、package、import和classpath
java分布式放置和调用
package和import
放置在同一个目录下面的类,类之间的相互调用无需显式声明调用。
统一目录下类名不可以相同
Java支持多个目录放置Java,并且package/import/classpath/jar等机制配合使用,可以支持跨目录放置和调用Java类。
package 包,和C++中namespace类似
类全称(长名称)=包名+类名
短名称=类名
p.s.包名package name和目录层次一样,尽量唯一,常用域名
引用类(即import package)的时候,必须采用全称引用;程序正文可以用短名称
pakage 1.2
import 1.2.example
//可以采用 import 1.2.*//*不可递归到所有子程序
//若example和当前类在同一目录下,可以省略上句的import
import 1.2.ex
//也可以采用import
总结
-Java通过包(package)来分开类
-package必须和目录层次一样
-Java通过引用(import)来导入类
-import类尽量准确
jar文件导出和导入
jar文件是一组class文件的压缩包,类似于C++的DLL
jar文件优势
-jar文件可以包括多个class,比多层目录更加简洁实用
-jar文件经过压缩,只有一个文件,在网络下载和传播方面 ,更具有优势
-jar文件只包括class,而没有包含java文件,在保护源文件知 识版权方面,能够可以起到更好的作用
-将多个class文件压缩成jar文件(只有一个文件),可以规定给一个版本号,更容易进行版本控制
-利用IDE的Export功能导出jar文件
-使用JDK自带的jar.exe。jar.exe位于JAVA_HOME的bin目录下。
classpath
包的具体位置可以在编译和运行的时候通过classpath再指定
java -classpath .;c:\temp cn.com.test.Man
第一部分:java,执行命令,是java.exe的简写。
第二部分:-classpath 固定格式参数,可以简写成-cp
第三部分:是一个(Windows分号,Linux/Mac冒号连接起来的) 字符串。按分隔符隔开,得到一个个子路径。当运cn.com.test.Man类的过程中,如果需要用到其他的类,就会分裂第三部分的字符串,得到多个子路径,然后依次在每个路径下,再去寻找相应类(全称,包名以点隔开对应到目录)。
第四部分:主执行类的全称(含包名)
编译和运行规则
- 编译一个类,需要java文件的全路径,包括扩展名。
- 运行一个类,需写类名全称(非文件路径),无须写扩展名。
- 编译类的时候,需要给出这个类所依赖的类(包括依赖的类再次 依赖的所有其他类)的所在路径。
- 运行类的时候,需要给出这个类,以及被依赖类的路径总和。
- classpath参数也可以包含jar包。如果路径内有空格,请将classpath 参数整体加双引号。
- java -classpath “.;c:\test.jar;c:\temp;c:\a bc” cn.com.test.Man
总结
- 包名和类所在的目录必须严格一致
- 在命令行中,必须依靠classpath来指引所需要的类
- 编译需要文件的全路径,运行需要类的完整名字
JAVA访问权限
JAVA访问权限:
- private: 私有的,只能本类访问
- default(通常忽略不写):同一个包内访问
- protected:同一个包,子类均可以访问
- public:公开的,所有类都可以访问
使用范围:
- 四种都可以用来修饰成员变量、成员方法、构造函数
- default和public可以修饰类
第八章、JAVA常用类
JAVA类库概述
- 官方文档目前以英文为主
- 可以下载文档离线版本(chm格式)
- 这些文档原先是程序中的注释。利用JavaDoc技术,将这些 注释抽取出来,组织形成的以HTML为表现形式的API (Application Programming Interface,应用编程接口)文档。
Java类库
- 包名以 java 开始的包是 Java 核心包 (Java Core Package)
- 包名以 javax 开始的包是 Java 扩展包 (Java Extension Package)
数字相关类
java.math包
Java 数字类
- 整数 Short, Int, Long
- 浮点数 Float, Double
- 大数类 BigInteger(大整数), BigDecimal(大浮点数)
- 随机数类 Random
- 工具类 Math
整数类型
- short,16位,2个字节,有符号的以二进制补码表示的整数
(-32768-32767, -215-215-1),默认值0 - int, 32位,4个字节,有符号的以二进制补码表示的整数
(-2147483648–2147483647, -231-231-1),默认值0 - long, 64位,8个字节,有符号的以二进制补码表示的整数 -9,223,372,036,854,775,808(-263)~9,223,372,036,854,775,807(263 -1),默认值0L
浮点数类型
- float,单精度,32位,4个字节,符合IEEE 754标准的浮点 数,默认值0.0f。float的范围为1.40129846432481707e-45 to 3.40282346638528860e+38 (无论正负)。
- double,双精度,32位,4个字节,符合IEEE 754标准的浮 点数,默认值0.0d。double的范围为4.94065645841246544e324d to 1.79769313486231570e+308d (无论正负) 。
- P.s.float和double都不能用来表示很精确的数字。
大数字类
- 大整数类BigInteger –支持无限大的整数运算
- 大浮点数BigDecimal –支持无限大的小数运算
- P.s.注意精度和截断 –查看BigDecimalTest.java
随机数类
- Random 随机数
- nextInt() 返回一个随机int
- nextInt(int a) 返回一个[0,a)之间的随机int
- nextDouble()返回一个[0.0,1.0]之间double
- ints 方法批量返回随机数数组
Math.random() 返回一个[0.0,1.0]之间double
数字工具类 • java.lang.Math:
绝对值函数abs;对数函数log;比较函数max、min;幂函数pow;四舍五入函数round等;向下取整floor;向上取整ceil
总结
- 根据数字特点选择合适的类
- 尽量使用类库自带的方法
- 浮点数需要注意精度
字符串相关类
Java中使用频率最高的类,是一个不可变对象,加减操作性能较差
常见方法:charAt, concat, contains, endsWith,equals, equalsIgnoreCase, hashCode, indexOf, length, matches, replace, replaceAll, split, startsWith, subString, trim, valueOf
可变字符串
- StringBuffer(字符串加减,同步,性能好)
- StringBuilder(字符串加减,不同步,性能更好)
StringBuffer/StringBuilder: 方法一样,区别在同步
- append/insert/delete/replace/substring
- length 字符串实际大小,capacity字符串占用空间大小
- trimToSize(): 去除空隙,将字符串存储压缩到实际大小
- P.s.如有大量append,事先预估大小,再调用相应构造函数
StringBuffer初始大小为(16+初始字符串长度)
时间相关类
Calendar;抽象类
Calendar gc=Calendar.getInstance();
Calendar gc= new GregorianCalendar();
- get(Field) 来获取时间中每个属性的值. 注意,月份0-11.
- getTime()返回相应的Date对象 –getTimeInMillis(), 返回自1970.1.1以来的毫秒数
- set(Field) 设置时间字段
- add(field, amount) 根据指定字段增加/减少时间
- roll(field, amount) 根据指定字段增加/减少时间,但不影响上一级的时间段
java.time包:新的Java日期/时间API的基础包
- java.time.chrono包:为非ISO的日历系统定义了一些泛化的API
- java.time.format包:格式化和解析日期时间对象的类
- java.time.temporal包:包含一些时态对象,可以用其找 出关于日期/时间对象的某个特定日期或时间
- java.time.zone包:包含支持不同时区以及相关规则的类
java.time包主要类
- LocalDate:日期类
- LocalTime:时间类(时分秒-纳秒)
- LocalDateTime: LocalDate + LocalTime
- Instant: 时间戳
格式化相关类
java.text包java.text.Format的子类
- NumberFormat:数字格式化,抽象类;DecimalFormat工厂模式
例如:将1234567格式化输出为1,234,567 - MessageFormat:字符串格式化
-支持多个参数值对位复制文本
-支持变量的自定义格式
例如将”Hello {1}”根据变量值格式化为Hello World - DateFormat:日期/时间格式化,抽象类;SimpleDateFormat工厂模式
-parse:将字符串格式化为时间对象
-format:将时间对象格式化为字符串
如将当前时间转为化YYYY-MM-DD HH24:MI:SS输出
java.time.format包下
-
DateTimeFormatter,时间格式化
线程安全(vs SimpleDateFormat 线程不安全)
java.time.format.DateFormatter:
- ofPattern: 设定时间格式
- parse:将字符串格式化为时间对象
- format:将时间对象格式化为字符串
如将当前时间转为化YYYY-MM-DD HH24:MI:SS输出
来源:CSDN
作者:汉堡里没有面包
链接:https://blog.csdn.net/qq_41433916/article/details/104301797