杂项
1.在一个源文件中,只能有一个公共类,但可有任意数目的非公共类。文件名必须与public类的名字匹配。
2.多个源文件,javac xxx.java,只指定包含main的源文件,会自动编译关联的其他源文件。java xxx,xxx为包含main的源文件不含后缀名。
3.每个类都可有一个main方法用于此类单元测试,运行进程时,采用指定名称类的main作为进程的main。
4.类型
- 基本数据类型
- 对象类型
T a = new T ( ) ;
T b = a;
包
- 包名
类似命名空间
- 类的导入
一个类可以使用所属包中的所有类,及其他包中的公共类。
import java. util. * ;
import java. sql. * ;
import java. util. Date;
var deadline = new java. util. Date ( ) ;
var deadline2 = new Data ( ) ;
import static java. lang. System. * ;
out. println ( "Hello" ) ;
- 类加入包
package com. horstmann. corejava;
public class Employee
{
. . .
}
. ( base directory)
com/
horstmann/
corejava/
Employee. java
Employee. class
mycompany/
PayrollApp. java
PayrollApp. class
javac com/ mycompany/ PayrollApp. java
java com. mycompany. PayrollApp
类存储在文件系统的子目录中。类的路径必须与包名匹配。
类文件也可存储在JAR文件中,一个JAR文件中,可包含多个压缩形式的类文件和子目录。
- 包访问
public 可由任意类使用
private 只可由定义它的类使用
默认 可被同一个包中方法访问
- 类路径
为了使类能被多个程序共享,需做到:
1.把类文件放到一个目录中。
如/home/user/classdir。
如希望增加com.horstmann.corejava.Employee类,
则Employee.class类文件就必须位于子目录
/home/user/classdir/com/horstmann/corejava中。
2.将JAR文件放在一个目录中。
如:/home/user/archives
3.设置类路径。类路径是所有包含类文件的路径的集合。
如:
/home/user/classdir:.:/home/user/archives/archive.jar
类路径包括:
1.基目录/home/user/classdir
2.当前目录
3.JAR文件/home/user/archives/archive.jar
archives目录中的所有JAR文件【不包括.class文件】都包含在这个类路径中。
类路径所列出的目录和归档文件是搜寻类的起始点。
一个示例
/home/user/classdir:.:/home/user/archives/archive.jar
假定虚拟机要搜寻com.horstmann.corejava.Employee类的类文件,
它首先查看Java API类。
转而查看类路径。然后查找以下文件:
/home/user/classdir/com/horstmann/corejava/Employee.class
com/horstmann/corejava/Employee.class
com/horstmann/corejava/Employee.class【/home/user/archives/archive.jar中】
编译器查找文件要比虚拟机复杂。
如引用了一个类,而没指定这个类的包,则编译器将首先查找包含这个类的包。
会查看所有的import指令,确定其中是否含这个类。
会在类路径所有位置中搜索各个可能类。如找到了一个以上的类,会编译报错。
- 设置类路径
java - classpath / home/ user/ classdir: . : / home/ user/ archives/ archive. jar MyProg
export CLASSPATH= / home/ user/ classdir: . : / home/ user/ archives/ archive. jar
JAR文件
一个JAR文件是压缩的,既可以包含类文件,也可包含诸如图像和声音等其他类型的文件。
- 创建JAR文件
jar cvf jarFileName file1 file2 . . .
- 清单文件
除了类文件,图像,其他资源,每个JAR还含一个清单文件,用于描述归档文件的特殊特性。
清单文件被命名为MANIFEST.MF,它位于JAR文件的一个特殊的META-INF子目录中。
要想编辑清单文件,需将希望添到清单文件中的行放到文本文件,然后运行
jar cfm jarFileName manifestFileName . . .
要创建一个含清单文件的JAR文件,应运行
jar cfm MyArchive, jar manifest. mf com/ mycompany/ mypkg
要想更新一个已有的JAR文件的清单,需将增加的部分放置到一个文本文件中,再执行以下
jar ufm MyArchive. jar manifest- additions. mf
- 可执行JAR文件
可使用jar命令中的e选项指定程序的入口点
jar cvfe MyProgram. jar com. mycompany. mypkg. MainAppClass files to add
或者,可在清单文件中指定程序的主类
Main- Class: com. mycompany. mypkg. MainAppClass
启动程序
java - jar MyProgram. jar
- 多版本JAR文件
要增加不同版本的类文件,可使用--release标志
jar uf MyProgram. jar -- release 9 Application. class
要从头构建一个多版本JAR文件,可使用-C选项,对应每个版本要切换到一个不同的类文件目录
jar cf MyProgram. jar - C bin/ 8 . -- release 9 - C bin/ 9 Application. class
面向不同版本编译时,要用--release标志和-d标志来指定输出目录
javac - d bin/ 8 -- release 8 . . .
- 文档注释
利用javadoc可以让文档和注释在一个地方
1.切换到包含想生成文档的源文件的目录
2.如是一个包,应运行
javadoc - d docDirectory nameOfPackage
如文件在无名的包中,应运行
javadoc - d docDirectory * . java
继承
1.多态
public class Manager extends Employee
{
added methods and fields
public Manager ( String name, double salary, int year, int month, int day)
{
super ( name, salary, year, month, day) ;
bonus = 0 ;
}
}
希望调超类Employee中的getSalary方法,而不是当前类的这个方法。需用。
public double getSalary ( )
{
return super. getSalary ( ) + bonus;
}
java中继承的基类的方法默认类似c++的virtual修饰的。如不希望基类某方法虚拟,将它标记为final。
2.final类和方法
用final修饰的类不可作为基类。
用final修饰的方法不可被子类覆盖。
3.基类转化为超类--带检查的
if ( staff[ 1 ] instanceof Manager)
{
boss = ( Manager) staff[ 1 ] ;
}
4.抽象方法与抽象类
用abstract修饰的方法为抽象方法,抽象方法不需提供实现。
含一个或多个抽象方法的类本身必须被声明为抽象的。抽象类可有字段,具体方法。
抽象类不可被实例化。
5.java的4个访问控制修饰符小结
private 仅对本类可见
public 对外部完全可见
protected 对本包和所有子类可见
默认 对本包可见
5.Object
未显示指定扩展的基类时,Object就是其基类。
在java中,只有基本类型不是对象。
数组及其他类均是对象。
- 相等检测示例
public class Employee
{
. . .
public boolean equals ( Object otherObject)
{
if ( this == otherObject) return true;
if ( otherObject == null) return false;
if ( getClass ( ) != otherObject. getClass ( ) )
{
return false;
}
Employee other = ( Employee) otherObject;
return Objects. equals ( name, other. name)
&& salary == other. salary
&& Objects. equals ( hireDay, other. hireDay) ;
}
}
public class Manager extends Employee
{
. . .
public boolean equals ( Object otherObject)
{
if ( ! super. equals ( otherObject) ) return false;
Manager other = ( Manager) otherObject;
return bonus == other. bonus;
}
}
6.哈希值
如果重新定义了equals方法,就需为用户可能插入散列表的对象重新定义hasCode方法。
hasCode方法应返回一个整数【也可是负数】
public class Employee
{
public int hashCode ( )
{
return 7 * Objects. hashCode ( name)
+ 11 * Double. hashCode ( salary)
+ 13 * Objects. hashCode ( hireDay) ;
}
public String toString ( )
{
return getClass ( ) . getName ( ) + "[name=" + name + ",salary=" + salary
+ ",hireDay=" + hireDay + "]" ;
}
}
public class Manager extends Employee
{
. . .
public String toString ( )
{
return super. toString ( ) + "[bonus=" + bonus + "]" ;
}
}
equals与hashCode的定义必须相容,
如x.equals(y)返回true,则x.hashCode()就必须与y.hashCode()返回相同的值。
7.对象包装器与自动装箱
有时需要将int这样的基本类型转换为对象。
所有基本类型都有一个与之对应的类。
如Integer类对应基本类型int。
通常,这些类称为包装器。
这些包装器类有显而易见的名字:Integer,Long,Float,Double,Short,Byte,Character,Boolean。
包装器类是不可变的,一旦构造了包装器,就不允许更改包装在其中的值。
包装器类还是final,不能派生它们的子类。
如要定义一个整形数组列表,尖括号中的类型参数不允许是基本类型,
如不允许ArrayList<int>。需用ArrayList<Integer>
var list = new ArrayList< Integer> ( ) ;
list. add ( 3 ) ;
int n = list. get ( i) ;
自动装箱规范要求boolean,byte,char<=127,介于-128 和127之间的short和int被包装到固定的对象中。
装箱和拆箱是编译器的工作。
8.枚举
java的枚举类型是强类型的。
enum Size
{
SMALL ( "S" ) ,
MEDIUM ( "M" ) ,
LARGE ( "L" ) ,
EXTRA_LARGE ( "XL" ) ;
private Size ( String abbreviation)
{
this. abbreviation = abbreviation;
}
public String getAbbreviation ( )
{
return abbreviation;
}
public String abbreviation;
}
9.反射
反射库提供了一个丰富且精巧的工具集,可以用来编写能动态操纵java代码的程序。
能够分析类能力的程序称为反射
- Class类
在程序运行期间,java运行时系统始终为所有对象维护一个运行时类型标识。
这个信息会跟踪每个对象所属的类。
虚拟机利用运行时类型信息选择要执行的正确的方法。