高新技术Day01
-------android培训、java培训、期待与您交流!----------
内容: MyEclipse小技巧、JDK1.5新特性、享元模式、枚举Enum、反射Reflect、反射类体系(Class、Field、Method、Constructir等)、数组反射应用、hashCode与equals作用、框架(Framework)。
一、MyEclipse相关知识:
1、在MyEclipse下如何查看一个变量的值(调试)?
右键Debug as,进入Debug透视图,在Expressions视图下添加查看的变量name(例:intx的x),之后通过左边的Debug视图的Resume(F8)等键来控制代码执行,可观察Expressions视图下变量值的变化。
2、显示需要的视图:
Window——>Show View——>...........(根据需要选择,要学会揣测)
3、编译器(javac)与运行器(java)的版本最好统一,而编译器版本不能高于运行器的版本,否则发生UnsupportedClassVersionE
Java源文件(.java) ———> 类文件(.class) ———> 内存中的字节码———> .....
4、可设置整个工作间或单个工程的javac、java的版本,即类似Java编程思想,继承父类,但可复写父类中方法(呵呵,MyEclipse也是用Java编写的嘛)。
5、编程时需要使用到jar包,通常MyEclipse都有默认的jar库,如果需要可以添加或修改jar文件,或修改、启用其他的库或者自定义库(自行添加jar文件到库中)。
6、MyEclipse中的快捷小操作:
A、自动生成类的构造函数:
右键——>Source(或Alt+Shift+S)——>Generate Constructor usingFields ;
2、自动生成类中的get、set()方法(获取、修改成员变量):
右键——>Source(或Alt+Shift+S)——> Generate Getter andSetter;等
3、打开运行对话框————> Arguments
————————————基础知识加强、补充————————————
一、 JDK1.5新特性:
1、静态导入:
作用:
2、可变参数:
public void sort(String str,int ...args)
调用格式:
——————知识点插曲——————
重载与重写的区别等:
Overload(重载):一个类中存在多个同名方法,但是只要它们的签名(接收)参数列表不同,Java就会将它们看做唯一的方法。这样两个参数列表不同的同名方法就称之为重载方法。
Override(重写):子类继承父类方法,参数列表与返回值类型完全相同,但是方法体内容(即方法执行代码)不同,这样就成为重写或覆盖父类方法。
Refactoring(重构):就是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。
PS: 重构这不是Java特性,而是MyEclipse等工具的功能,例如: 可改变所有使用到某个变量的.java文件中该变量名或通过改变某个变量的参数类型使对应的Java类使用新的参数Java类,实现更新升级等。
简单概括:
1、重载: 存在于同一个类中,只看同名函数的参数列表;
2、重写: 存在于子父类间,子父类方法(参数列表与返回值类型)一样,方法体内容不同。
3、重构: 软件程序的内部结构的调整,是实现“事先设计”的基础。
————————————
3、高级for循环【详见集合篇之高级for循环】
for(final String s : str){
4、基本数据类型对象的自动装箱和拆箱:
字节byte:
设计模式之“享元模式”(Flyweight Pattern):
解析:
【代表: 在java中如果用到1字节(byte)以内的数字 它会把他缓存起来进行复用,即使是newInteger对象也是指向相同的地址值。】
内部状态与外部状态:
将小对象(26字母、-128到127之间数字、char等常见关键字,应该就放在静态区)
而不同的东西变成方法(参数)属性,是外部状态,而那些小对象组成的(整个单体)就是内部状态。
示例比喻:
———————————————枚举(Enum)———————————————
二、枚举: Enum,就是一个特殊的类;
枚举符号: enum;
注:
其他:
1、类的方法返回值类型可以是本类对象;
2、类中可定义静态常量,例如Math.PI(即π)、Integer.MAX_VALUE(int型最大值2^31-1);
【当静态常量的类型是本类类型且指向的是本类实例对象时,枚举可简化书写】
枚举(java.lang.Enum):
一般方法:
toString()
ordinal()
getDeclaringClass()
【不同于Object.getClass(),getClass()方法返回值带有枚举常量(枚举角标等)】
静态方法:
valueOf(String str)
values()
解析:
(一)为避免思路错乱,先整理下知识:
创建类的实例化对象的方式:
1、常见new 对象:
//以下两种属于私有化构造函数的情况;
2、通过方法获取实例化对象:
3、通过类类型的静态变量来获取:
调用:
(二)枚举的特点/优点:
1、简化获取构造函数的代码书写;
即简化静态常量(变量)的类型是本类类型且指向的是本类实例对象时的代码书写。
2、注意:枚举属于饿汉式,一进内存就会加载。
(例如: 当加载枚举的类文件时,构造函数存在打印语句,在加载时就会直接打印输出)
3、提示:
饿汉式的单例(设计模式),可以用只有一个成员(枚举值)的枚举来实现,可简化代码。
———————————————反射(Reflect)——————————————
三、反射:(Reflect)
基石: ——>
可理解为:
import java.util.TreeSet;
理解:
【所以在写程序时要尽可能明确调用的类,尽量不要"java.util.*;",因为这会在内存加载整个util包中的类的字节码文件,也就会占用多余的内存。】
(Java程序在加载时至少要加载哪些字节码文件?————
联系理解:
人以及人的属性、行为————>Person类
Java类以及变量、方法————>Class类
Java类与反射体系图
【PS: 下文会对反射体系中各成员进行详解】
(一)获得Class类的对象:
A、类名.class;
B、对象.getClass();
C、Class.forName("java.util.Date");【反射应用的基础,将字符串的值定义成变量】
【举例帮助理解:
以泛型适配符T为例,Collection :定义该集合要接收一种数据类型,但是接收类型不明确,为了提高扩展性,就将接收的数据类型定为变量T,实际使用时传入什么数据类型就需要对变量T进行赋值,因此就可根据变量T去调用所需要的数据类型(的字节码),而这个调用的过程就相当于反射。
也就可理解Class.forName()为什么是反射主要的应用方式,因为调用数据类型不明确】
(二)返回Class(字节码)的两种方式:
A、该字节码文件已在内存中存在,直接调用并返回该字节码;(上面的三者均可)
B、该字节码未在内存中存在,加载该字节码文件,然后返回该字节码;(通常是第三种)
(因为通过对象调用或类名调用,则该类的字节码肯定已经在加载到内存)
(三)九种预定义的实例对象(Class对象):
1、void.class;
2、8个基本数据类型(boolean、int等);
解析(个人观点,仅供参考):
在编写Java程序时常用到的是java.lang包中的类以及8个基本数据类型与void(这9个好像没有在API中占一席地,也就不包括在lang包),因此加载时除了lang包,也就要有预定义的实例对象。
【Void等类的TYPE是对应这9个预定义的class对象,仅供理解。】
对应如下: (获取基本数据类型字节码的方法)
void.class == Void.TYPE;(true),而void.class == Void.class; (false);
(即: 8种基本数据类型以及void,在Java中可通过八种基本数据类型包装类的静态常量TYPE获得对应字节码。)
(四)其他:
1、数组类型的Class实例对象:
2、Class类方法:
T
而Constructor.newInstance(Object...initargs)返回(可变参数列表的)构造方法】
————————————反射类————————————
四、反射类体系:
在Java中,将一个Java类用Class类的对象来表示,而该Java类中的变量、方法、构造方法、包、修饰符等信息,就是用相应类的实例对象来表示: Field、Method、Constructor、Package等等。
注意:
1、程序开发时要明确代码编译和运行的执行范围(编译时异常、运行时异常)
2、反射的缺点: 会导致程序性能严重下降(运行速度有所下降,相对计算机运行效率而已)
【建议:当重复反射调用某个类时,应该根据情况将反射获取到的字节码进行缓存,减少重复反射的动作等】
理解:
1、因为每个类被加载到内存时,都会被加载字节码class(该字节码唯一,且包含该类的属性信息: 包名、成员变量、方法等);
2、通过反射获取到该字节码class属于Class类,而Class类中存在获取其他类中的属性信息的方法(类似集合中存在的iterator()方法)。
3、通过这些getMethod、getField()等方法,可以对其他类中的属性、行为等进行操作、修改等(这就是反射的应用)。
———————————————反射中的成员类——————————————
五、反射中的成员类:
(一)Field类:(成员变量)
1、创建Field对象的Class类方法:
.getField(String name)
.getDeclaredField()
Filed[]
2、Field类的方法:
get(Object obj)
【继承java.lang.reflect.AccessibleObject的方法:】
(注: 用于getDeclareField方法返回的private成员变量,使其可被get(obj)方法获取。)
———————————————
(二)Method类:
1、创建Method对象的Class类方法:
2、Method类的方法:
.invoke(原来调用的对象,方法中的参数); :
3、代码示例:
通常方式: String str = "abc"; str.charAt(2);
反射方式: Method methodCharAt =String.class.getMethod("charAt",int.class);
methodCharAt.invoke(str,2);
4、注意:
A、因为静态方法不需要指定调用方法的对象,所以当调用静态方法时可以将"原来参数"可定义为null,即不需要对象就能调用的方法(类名调用);
B、疑惑:method.invoke(main.class,(Object)new String[]{"hehe","xixi"});
解析: 需要添加(Object)或用new Object[]{...}包装的原因是
Method类中的方法: .invoke(Object obj,Object...args)由于Object...args兼容Object[]数组,所以当传入值类型属于Object[]或其子类时会被拆包。
————————————
(三)其他成员获取方法:
Class<?>[]
Constructor<T>
Package
ClassLoader
(其他)面试题:
1、如果使用无参的构造函数,直接使用Class类的new Instance()方法即可;
2、若需要使用特定的构造函数来创建对象,则需要先获取Constructor实例,再用new Instance()方法创建对象。
——————————————数组反射应用——————————————
六、数组反射:
1、int[]等是基本数据类型数组(属于Array类,数组),也就是说整个int[]等是Object对象,是可以调用Object类的方法等。
2、打印数组中元素的方式(只能打印对象类型数组):
通过Arrays.asList()方法将数组变成集合,而sop(集合)时能明了查看到集合中的元素。
PS:不能实现对int[]等基本类型数组转换查看的原因是转换时将整个int[]数组作为一个对象存储到集合中,所以打印出来的依旧是基本类型数组的地址值。
3、遍历数组的新方式(通过反射实现):
String[] obj = new String[]{"hehe","xixi","haha"};
//以反射形式遍历数组的方法:
private static void sortArray(Object obj){
4、无法获取整个数组的元素数据类型,只能通过数组中某个元素获取其对应数据类型(通过字节码来获取类型)。
例:
有点烂的例子:
(其他)英文异常提醒:
Unhandled exception(没有处理异常) typeClassNotFoundException(类找不到异常);
七、字节码之间的比较:
1、基本数据类型(int等)只能用类名获取字节码,而基本数据类型对象与基本数据类型数组等可通过类名或变量名获得对应的字节码;
2、数据类型(基本、引用与数组数据类型)间字节码比较符使用:
【特殊:基本数据类型与对应的基本包装类的class字节码可用"=="号进行比较,但是基本数据类型数组与对应的包装类对象数组则不能用"=="号进行比较。】
3、类型提升比较: 当方法接收类型参数或以多态形式赋值时,父类变量调用方法获得的字节码可与其子类字节码用"=="进行比较。
理由:由于类型提升与Java编译检测方式(水平有限,说不清,偏向前者多一点).
例:
字节码"=="比较编译解析:
sop(num.getClass()==String.class);
sop(Number.class==Long.class);
sop(new Long(33).getClass()==Number.class);
【数组数据类型也适用,不过也受第2条中“特殊”情况的限制。】
4、通过反射获得class类型可以任意类型进行比较;(理由如下)
例: class string类:
【同理: 因为Java泛型是伪泛型(编译后会类型擦除),所以也可通过反射来给带泛型的集合添加任意有效元素。】
5、警惕:
例如:
——————————————————————————————
八、hashCode与equals的作用:
hashCode与equals的关系与作用:
1、存储到hashSet、hashMap等集合/映射中的元素对象应该复写hashCode()与equals()方法,使元素对象具备比较性;
2、存储到hashSet集合时先比较两个对象hashCode值,如果相同再用equals比较。
【因此两个对象的equals相同时,它们的hashCode值必定相同;反之则不一定。】
特殊知识点:
1、无法对该对象进行删除等依靠hashCode值比较判断的操作;
2、修改后该对象的哈希值无效,也就无法参与比较,当存储元素内容相同(哈希值相同)的元素时,可以被存储进该集合,导致HashSet(或HashMap)中的元素不唯一。
3、当对集合中的多数对象进行相同操作时,由于旧的元素没有在内存中删除,不断占用内存,加剧内存泄漏;当存在大规模该问题时甚至导致内存溢出(异常)。
【提醒:注意此情况,可联系实际,在解答或使用hashCode时注意/提及内存泄漏问题,当然也可以用此例子作为内存泄漏的案例。】
名词解析:
————————————————框架(Framework)——————————————
九、框架(Framework):
框架:
工具类:
以房子为例,房屋即为一个框架,它有提供一个安装门的位置,等待住户根据需要安装不同类型的门(门亦为工具类,被选择调用),而房屋调用门,使其具备门的特有属性(防盗等)。
Java三大框架:
Spring:
Struts:
Hibernate:
通俗总结:简称SSH,其中Structs主要用来做表现层的,Hibernate是用来做DAO(数据访问)层的,而Spring是用来联系起两者的。
框架的简单构建:
1、创建配置文件:(config.properties)用于存储所需的程序调用属性信息;
2、构建框架类:通过IO流或类加载器读取配置文件中的信息,将信息资料通过反射转换成类实例对象等,从而去执行指定的操作动作与行为。
功能作用:
(例: 修改反射集合,*选择存储集合为ArrayList或TreeSet等,或者修改调用类、接口,选用不同功能或升级后的类程序)
备注:
1、Properties映射(可从流中读取或保存数据的Hashtable的子类,键值均为字符串)。
2、关闭close流的原因:
3、配置文件的路径设置:
//getRealPath()/内部位置;
4、读取配置文件的方式:
A、IO流,可读可写,但配置路径难以与调用的Java程序关联一致(因此仅使用写入功能);
B、调用的Java源文件的类加载器的getResourceAsStream()方法加载(可使用相对路径,注意:类加载器只能加载文件信息,不能写入数据);
C、建议:Java源文件的getResourceAsStream()方法加载(底层是类加载器,简化了代码,可使用相对或绝对路径,但绝对路径是基于文件安装位置起的)。
【示例:
完整路径: FilePath/com/DemoDay/java.properties
相对路径: java.properties
绝对路径: /com/DemoDay/config.properties
5、其他:
(1)框架的配置文件存储在classPath路径下,因为框架加载配置文件方式是类加载器加载。
(2)软件开发中的三种级别重用:
A、内部重用,即在同一应用中能公共使用的抽象块;
B、代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;
C、应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得*的重用性。
【实例为框架,例:Work软件等,提供框架平台,使用者根据需要选择工具等来添加文字或图片等,实现自己所需的结果】
(3)框架与设计模式:
框架:可以是调用其他类的类或软件等,一个框架中往往含有一种或多种设计模式;
设计模式:是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象,可以看做是软件的知识。