Java核心技术1
Java方法参数的使用情况:
- 一个方法不能修改一个基本数据
对象析构与finalize方法
Java有自动的垃圾回收器,不需要人工回收内存,例如,文件或使用了系统资源的另一个对象的句柄。在这种情况下,当资源的不再需要时,将其回收和再利用将显得十分重要。可以为任何一个类添加 finalize 方法。finalize 方法将在垃圾回收器清除对象之前调用 。在实际应用中,不要依赖于使用finalize 方法回收任何短缺的资源 , 这是因为很难知道这个方法什么时候才能够调用。(这点其实是和net机制是一样的)
包
Java包概念其实就是net中命名空间
- 静态导入,这样就可以使用静态方法和静态域,比如out.println() import static java . lang . System . * ;
Javadoc生成文档
继承
- 通过super调用父类方法,相当于net中的base
- 静态绑定是 private 方法 、 static 方法或 final 方法,除此是动态绑定
- 在 Java 中 ,不需要将方法声明为虚拟方法 。动态绑定是默认的处理方式 。如果不希望让一个方法具有虚拟特征 ,可以将它标记为 final
- 每次调用方法都要进行搜索,时间开销相当大。因此,虚拟机预先为每个类创建了一个方法表( method table ) , 其中列出了所有方法的签名和实际调用的方法。这样一来 ,在真正调用方法的时候 , 虚拟机仅查找这个表就行了。
- 在 C # 中 ,如果没有特别地说明(virtual) ,所有的方法都不具有多态性 。这两种做法可能都有些偏激 。
-
综上所述 : • 只能在继承层次内进行类型转换 。 • 在将超类转换成子类之前 ,应该使用instanceof 进行检查。
-
abstract中可以包含具体实现,不能被实例化,同C#是一样的。
Java 中它允许在运行时确定数组的大小
对象中的数据称为实例域 ( instance field ) , 操纵数据的过程称为方法 ( method )
泛型数组列表
-
数组列表(ArryList)的容量与数组的大小有一个非常重要的区别。如果为数组分配 100 个元素的存储空间,数组就有100 个空位置可以使用 。而容量为 100 个元素的数组列表只是拥有保存 100 个元素的潜力 ( 实际上,重新分配空间的话 , 将会超过100 ) , 但是在最初 ,甚至完成初始化构造之后 ,数组列表根本就不含有任何元素 。
-
一旦能够确认数组列表的大小不再发生变化,就可以调用 trimToSize 方法 。这个方法将存储区域的大小调整为当前元素数量所需要的存储空间数目。垃圾回收器将回收多余的存储空间。
包装器
有时,需要将 int 这样的基本类型转换为对象。所有的基本类型都冇一个与之对应的类。。例如,Integer 类对应基本类型 int.通常,这些类称为包装器( wrapper )
装箱和拆箱是编译器认可的,而不是虚拟机。编译器在生成类的字节码时,插人必要的方法调用。虚拟机只是执行这些字节码 。
继承的设计技巧
- 将公共操作和域放在超类
- 不要使用受保护的域
- 使用继承实现“is-a”关系(父子关系)
-
除非所有继承的方法都有意义,否则不要使用继承
-
在覆盖方法事,不要改变预期的行为 假如我就是要这样设计,Holiday类继承GregorianCalendar类,那么我只能把共有方法add覆盖成合理的代码,或者什么都不做,或者抛出一个异常。但是add方法变味了,变的不像我当初设计的那样了。这里作者的意思是:不要这样,在覆盖父类中的方法时,不要偏离最初的设计想法。
-
使用多态,而非类型信息
- 不要过多地使用反射
接口
有了抽象类为什么还要引入接口?
使用抽象类表示通用属性存在这样一个问题:每个类只能扩展于一个类。 接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。
jdk1.8新特性
-
接口中支持静态方法
public interface InterfaceA { static void getName() { System.out.println("6666"); } }
-
默认方法
public interface InterfaceA { default void getName() { System.out.println("6666"); } }
-
默认方法解决冲突
-
超类优先
- 接口冲突
内部类
- 一个方法可以引用调用这个方法的对象数据域,内部类既可以访问自身的数据域, 也可以访问创建它的外围类对象的数据域。
- 外围类的引用在构造器中设置,编译器修改了所有内部类的构造器,添加了一个外围类的引用参数。
-
内部类是一种编译器现象,与虚拟机无关。编译器将会把内部类翻译成用$分隔外部类名与内部类名的常规类文件,而虚拟机则对此一无所知。
TalkingClock$TimePrinter.class
内部类:https://www.cnblogs.com/chenssy/p/3388487.html
代理类
https://segmentfault.com/a/1190000011291179
异常分类
- 所有异常都是派生自Throwable类,分为Error和Exception
- Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误,应用程序不应该抛出这类错误。
- 应用程序出错需要关注Exception
- 如果出现RuntimeException异常,那么就一定是你的问题。
- Java语言规范将 派生于Error类或RuntimeException类的所有异常称为非受( unchecked ) 异常。
- 所有其它的异常称为受查异常。
如果在子类中覆盖了超类的一个方法,子类方法中声明的受查异常不能比超类方 法中声明的异常更通用( 也就是说,子类方法中可以抛出更特定的异常,或者根本不抛出任何异常。特别需要说明的是,如果超类方法没有抛出任何受查常,子类也不能抛出任何受查异常。
带资源的try语句 try - with - resources ) 的最简形式为 : try ( Resource res = . . . ) { work with res }
try块退出时,会自动调用res.close。
堆栈轨迹
静态的Thread.getAllStackTrace()方法,它可以产生所有线程的堆栈轨迹。
Map<Thread,StackTraceElement[ ]> map = Thread.getAl1StackTraces();
for ( Thread t : map .keySet())
{
StackTraceElement[ ] frames = map.get( t ) ;
analyze frames
}
日志
-
全局日志记录器
Logger.getClobal().info()
-
关闭/开启所有级别记录
Logger.getClobal().setLevel(Level.OFF)
Level.ALL
-
获取记录器
private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp")
-
修改日志管理器配置
配置文件地址:
jre/lib/1ogging.properties
日志管理器在VM启动过程中初始化,这在 main 执行之前完成。如果在main中调用 System.setProperty("java.util.logging.config.file",file) ,也会调用LogManager.readConfiguration( )来重新初始化曰志管理器。
泛型
前期泛型程序设计是用继承实现的,ArrayList类只维护一个Object引用的数组:
public class ArrayList{
private Object [ ] elementData;
public Object get ( int i ) { }
public void add ( Object o ) { }
}
问题
这种方式存在的问题:
- 当获取一个值时必须进行强制类型转换
- 这里没有错误检査。可以向数组列表中添加任何类的对象对于这个调用,编译和运行都不会出错。然而在其他地方,如果将 get 的结果强制类型转换为 String 类型,就会产生一个错误。
泛型约束
public static <T extends Coiparab1e> T min(T[] a)
{
}
一个类型变量或通配符可以有多个限定,T extends Comparable & Serializable 限定类型用 “ & ” 分隔,而逗号用来分隔类型变量
Net泛型和Java泛型区别
- 1. net泛型
https://www.cnblogs.com/DebugLZQ/archive/2012/09/03/2669383.html
- 2. java泛型
https://www.cnblogs.com/drizzlewithwind/p/6101081.html
- 3. 本质区别
https://blog.csdn.net/tianshiainiforever/article/details/51698863
- 不能创建参数化类型的数组
- 泛型类的静态上下文中类型变量无效
Java泛型系列
- 基本用法与类型擦除
- 泛型与数组
- 通配符的使用
https://segmentfault.com/a/1190000005337789
集合
Iterator 接口的 remove 方法将会删除上次调用 next 方法时返回的元素。 在决定删除某个元素之前应该先看一下这个元素是很具有实际意义的。然而,如果想要删除指定位置上的元素,仍然需要越过这个元素。如果调用remove之前没有调用 next 将是不合法的。如果这样做,将会抛出一个 IllegalStateException 异常。
Iterator<String> it = c.iterator();
it.next();
it.remove();
链表
数组列表
散列表
树集
队列与双端队列
优先级队列
优先级队列使用了一个优雅且高效的数据结构,称为堆( heap )。堆(可不是jvm中的堆)是一个可以自我调整的二叉树,对树执行添加( add ),和删除 ( remore ) 操作,可以让最小的元素移动到根,而不必花费时间对元素进行排序。
- PriorityQueue