Java新手入门的30个基本概念
前言:
在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SE是Java的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念。
Java概述:
目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合pc应用程序的开发,其发展逐渐变成在开发手持设备,互联网信息站,及车载计算机的开发.Java于其他语言所不同的是程序运行时提供了平台的独立性,称许可以在windows,solaris,linux其他操作系统上使用完全相同的代码.Java的语法与C++语法类似,C++/C程序员很容易掌握,而且Java是完全的彻底的面向对象的,其中提出了很好的GC(Garbage Collector)垃圾处理机制,防止内存溢出。
Java的白皮书为我们提出了Java语言的11个关键特性。
(1)Easy:Java的语法比C++的相对简单,另一个方面就是Java能使软件在很小的机器上运行,基础解释其和类库的支持的大小约为40kb,增加基本的标准库和线程支持的内存需要增加125kb。
(2)分布式:Java带有很强大的TCP/IP协议族的例程库,Java应用程序能够通过URL来穿过网络来访问远程对象,由于servlet机制的出现,使Java编程非常的高效,现在许多的大的web server都支持servlet。
(3)OO:面向对象设计是把重点放在对象及对象的接口上的一个编程技术.其面向对象和C++有很多不同,在与多重继承的处理及Java的原类模型。
(4)健壮特性:Java采取了一个安全指针模型,能减小重写内存和数据崩溃的可能型。
(5)安全:Java用来设计网路和分布系统,这带来了新的安全问题,Java可以用来构建防病毒和防攻击的System.事实证明Java在防毒这一方面做的比较好。
(6)中立体系结构:Java编译其生成体系结构中立的目标文件格式可以在很多处理器上执行,编译器产生的指令字节码(Javabytecode)实现此特性,此字节码可以在任何机器上解释执行。
(7)可移植性:Java中对基本数据结构类型的大小和算法都有严格的规定所以可移植性很好。
(8)多线程:Java处理多线程的过程很简单,Java把多线程实现交给底下操作系统或线程程序完成.所以多线程是Java作为服务器端开发语言的流行原因之一。
(9)Applet和servlet:能够在网页上执行的程序叫Applet,需要支持Java的浏览器很多,而applet支持动态的网页,这是很多其他语言所不能做到的。
基本概念:
1.OOP中唯一关系的是对象的接口是什么,就像计算机的销售商她不管电源内部结构是怎样的,他只关系能否给你提供电就行了,也就是只要知道can or not而不是how and why.所有的程序是由一定的属性和行为对象组成的,不同的对象的访问通过函数调用来完成,对象间所有的交流都是通过方法调用,通过对封装对象数据,很大限度上提高复用率。
2.OOP中最重要的思想是类,类是模板是蓝图,从类中构造一个对象,即创建了这个类的一个实例(instance)。
3.封装:就是把数据和行为结合起在一个包中)并对对象使用者隐藏数据的实现过程,一个对象中的数据叫他的实例字段(instance field)。
4.通过扩展一个类来获得一个新类叫继承(inheritance),而所有的类都是由Object根超类扩展而得,根超类下文会做介绍。
5.对象的3个主要特性
behavior---说明这个对象能做什么.
state---当对象施加方法时对象的反映.
identity---与其他相似行为对象的区分标志.
每个对象有唯一的indentity 而这3者之间相互影响.
6.类之间的关系:
use-a :依赖关系
has-a :聚合关系
is-a :继承关系--例:A类继承了B类,此时A类不仅有了B类的方法,还有其自己的方法.(个性存在于共性中)
7.构造对象使用构造器:构造器的提出,构造器是一种特殊的方法,构造对象并对其初始化。
例:Data类的构造器叫Data
new Data()---构造一个新对象,且初始化当前时间.
Data happyday=new Data()---把一个对象赋值给一个变量happyday,从而使该对象能够多次使用,此处要声明的使变量与对象变量二者是不同的.new返回的值是一个引用。
构造器特点:构造器可以有0个,一个或多个参数
构造器和类有相同的名字
一个类可以有多个构造器
构造器没有返回值
构造器总是和new运算符一起使用.
8.重载:当多个方法具有相同的名字而含有不同的参数时,便发生重载.编译器必须挑选出调用哪个方法。
9.包(package)Java允许把一个或多个类收集在一起成为一组,称作包,以便于组织任务,标准Java库分为许多包.java.lang java.util java,net等,包是分层次的所有的java包都在java和javax包层次内。
10.继承思想:允许在已经存在的类的基础上构建新的类,当你继承一个已经存在的类时,那么你就复用了这个类的方法和字段,同时你可以在新类中添加新的方法和字段。
11.扩展类:扩展类充分体现了is-a的继承关系. 形式为:class (子类) extends (基类)。
12.多态:在java中,对象变量是多态的.而java中不支持多重继承。
13.动态绑定:调用对象方法的机制。
(1)编译器检查对象声明的类型和方法名。
(2)编译器检查方法调用的参数类型。
(3)静态绑定:若方法类型为priavte static final 编译器会准确知道该调用哪个方法。
(4)当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用x所指向的对象的实际类型相匹配的方法版本。
(5)动态绑定:是很重要的特性,它能使程序变得可扩展而不需要重编译已存代码。
14.final类:为防止他人从你的类上派生新类,此类是不可扩展的。
15.动态调用比静态调用花费的时间要长。
16.抽象类:规定一个或多个抽象方法的类本身必须定义为abstract。
例: public abstract string getDescripition
17.Java中的每一个类都是从Object类扩展而来的。
18.object类中的equal和toString方法。
equal用于测试一个对象是否同另一个对象相等。
toString返回一个代表该对象的字符串,几乎每一个类都会重载该方法,以便返回当前状态的正确表示.
(toString 方法是一个很重要的方法)
19.通用编程:任何类类型的所有值都可以同object类性的变量来代替。
20.数组列表:ArrayList动态数组列表,是一个类库,定义在java.uitl包中,可自动调节数组的大小。
21.class类 object类中的getclass方法返回ckass类型的一个实例,程序启动时包含在main方法的类会被加载,虚拟机要加载他需要的所有类,每一个加载的类都要加载它需要的类。
22.class类为编写可动态操纵java代码的程序提供了强大的功能反射,这项功能为JavaBeans特别有用,使用反射Java能支持VB程序员习惯使用的工具。
能够分析类能力的程序叫反射器,Java中提供此功能的包叫Java.lang.reflect反射机制十分强大.
1.在运行时分析类的能力。
2.在运行时探察类的对象。
3.实现通用数组操纵代码。
4.提供方法对象。
而此机制主要针对是工具者而不是应用及程序。
反射机制中的最重要的部分是允许你检查类的结构.用到的API有:
java.lang.reflect.Field 返回字段.
java.reflect.Method 返回方法.
java.lang.reflect.Constructor 返回参数.
方法指针:java没有方法指针,把一个方法的地址传给另一个方法,可以在后面调用它,而接口是更好的解决方案。
23.接口(Interface)说明类该做什么而不指定如何去做,一个类可以实现一个或多个interface。
24.接口不是一个类,而是对符合接口要求的类的一套规范。
若实现一个接口需要2个步骤:
1.声明类需要实现的指定接口。
2.提供接口中的所有方法的定义。
声明一个类实现一个接口需要使用implements 关键字
class actionB implements Comparable 其actionb需要提供CompareTo方法,接口不是类,不能用new实例化一个接口.
25.一个类只有一个超类,但一个类能实现多个接口。Java中的一个重要接口:Cloneable
26.接口和回调.编程一个常用的模式是回调模式,在这种模式中你可以指定当一个特定时间发生时回调对象上的方法。
例:ActionListener 接口监听.
类似的API有:java.swing.JOptionPane
java.swing.Timer
java.awt.Tookit
27.对象clone:clone方法是object一个保护方法,这意味着你的代码不能简单的调用它。
28.内部类:一个内部类的定义是定义在另一个内部的类。
原因是:
1.一个内部类的对象能够访问创建它的对象的实现,包括私有数据。
2.对于同一个包中的其他类来说,内部类能够隐藏起来。
3.匿名内部类可以很方便的定义回调。
4.使用内部类可以非常方便的编写事件驱动程序。
29.代理类(proxy):
1.指定接口要求所有代码
2.object类定义的所有的方法(toString equals)
30.数据类型:Java是强调类型的语言,每个变量都必须先申明它都类型,java中总共有8个基本类型.4种是整型,2种是浮点型,一种是字符型,被用于Unicode编码中的字符,布尔型。
利用VC访问INI文件和系统注册表
本文主要对私有、系统初始化文件和系统注册表的访问方法作了较深入的讨论。
关键词: VC++6.0;初始化文件;系统注册表;
.INI文件
INI文件(Initialization file ,又称为初始化文件)是用来保存应用程序设置和选项的一种特殊的ASCII文件,以“.ini”作为文件扩展名,也被称做配置文件或概要文件(Profile)。除了各个应用程序可以拥有自己私有的初始化文件外,Windows系统还提供有一个系统的初始化文件Win.ini,并由此对当前的Windows系统进行配置,同时也可以在其内记录系统内其他应用程序在运行时的选项。
通常为应用程序所私有的初始化文件比较小,这样可以减少程序在初始化时所读取的信息量,从而提高程序的启动速度。而系统初始化文件Win.ini由于除了记录有关系统的大量信息外,还存储着许多其他应用软件的初始化数据,因此其通常比较庞大,访问的数据量要远比私有的配置文件大得多。如没有必要,一般不建议对Win.ini文件进行操作,但如果待存取的信息涉及到Windows系统环境或是其他应用程序时, 就必须对Win.ini进行读写访问,并在访问的同时发送WM_WININICHANGE消息给所有的顶层窗口,通知其他进程系统初始化文件已被更改。
配置文件里的信息之所以能为系统和众多不同类型的应用程序读取并识别,是由于其内部对数据的存取采用了预先约定的“项-值对(Entry-value pairs)”存储结构, 并对待存取的数据分门别类地进行存储。下面是系统目录下Win.ini文件的部分内容:
[windows]
load=
run=
NullPort=None
[Desktop]
WallpaperStyle=2
Pattern=(无)
在此,配置文件将信息分为若干“节”,节标题放在方括号中,如“[Desktop]”就是Desktop节,在每一个节中包含了一些与之相关的“项”,并通过等号对其进行赋值。一般形式如下:
[SECTION]
ENTRY=VALUE
在初始化文件中,VALUE值只能有两种数据类型:数值和字符串。Windows分别为这两种数据类型提供了两套API函数对初始化文件进行数据读取,在写入初始化文件时则只支持对字符串的写入,数值等类型必须先进行数据类型的转换,然后才能写入到初始化文件。
私有初始化文件的访问
对私有初始化文件的数据存取是由GetPrivateProfileInt()、GetPrivateProfileString()和WritePrivateProfileString()等三个API函数来完成的。其函数说明如下:
UINT GetPrivateProfileInt(LPCTSTR lpAppName, // 节名地址
LPCTSTR lpKeyName, // 项名地址
INT nDefault, // 在项名没有找到时返回的缺省值
LPCTSTR lpFileName // 初始化文件名地址
);
DWORD GetPrivateProfileString(LPCTSTR lpAppName, // 节名地址
LPCTSTR lpKeyName, // 项名地址
LPCTSTR lpDefault, // 缺省字符串
LPTSTR lpReturnedString, // 存放字符串的缓冲区地址
DWORD nSize, // 缓冲区大小
LPCTSTR lpFileName // 初始化文件名地址
);
BOOL WritePrivateProfileString(LPCTSTR lpAppName, // 节名地址
LPCTSTR lpKeyName, // 项名地址
LPCTSTR lpString, // 要写入的字符串地址
LPCTSTR lpFileName // 初始化文件名地址
);
其中,GetPrivateProfileInt()返回的是初始化文件lpFileName中lpAppName节内lpKeyName项的整数值,如果没有找到该项则返回缺省值nDefault。如果此项目存在,但值不为整数,则返回0。如果某项目的值中含有非数字字符则只返回第一个非数字前的字符,例如对于“Value = 21century”则只返回数值21。初始化文件名lpFileName可以是全路径也可以只是文件名,如果不指定具体路径,Windows系统将在系统目录对文件进行寻找。GetPrivateProfileString()和WritePrivateProfileString()的用法基本与之类似,只是处理对象的数据类型不同。
私有初始化文件主要用来保存同应用程序当前状态相关的一些信息,当程序退出后,这些信息由于已写入到初始化文件而得以保留,当程序再次运行时,可以通过对此初始化文件各项数据的读取而得知此应用程序在上次运行期间的相关信息。下面这段代码即通过对私有初始化文件的访问而对程序的运行次数和上一次的运行日期进行记录:
// 获取当前应用程序全路径
GetModuleFileName(NULL, buffer, MAX_PATH);
sPath = CString(buffer);
sPath = sPath.Left(sPath.ReverseFind('\\'));
// 得到初始化文件的全路径
sPath += "\\Sample04.ini";
// 得到程序累计运行次数
UINT Time = GetPrivateProfileInt("PROGRAM", "RUNTIME", 0, sPath);
// 得到上次运行日期
GetPrivateProfileString("DATE", "LAST", "2002-11-1", buffer, 1000, sPath);
// 显示从初始化文件获取到的文件信息
sMsg.Format("本软件共运行过%d次,上次运行日期为%s", Time, CString(buffer));
AfxMessageBox(sMsg);
// 累加运行次数,并保存到初始化文件
Time++;
sTime.Format("%d", Time);
WritePrivateProfileString("PROGRAM", "RUNTIME", sTime, sPath);
// 获取当前日期,并保存到初始化文件
CTime tm = CTime::GetCurrentTime();
sDate.Format("%d-%d-%d", tm.GetYear(), tm.GetMonth(), tm.GetDay());
WritePrivateProfileString("DATE", "LAST", sDate, sPath);
在程序执行后,初始化文件Sample04.ini的内容为:
[DATE]
LAST =2002-11-12
[PROGRAM]
RUNTIME =1
对Win.ini的访问
系统目录下的Win.ini是一种特殊的初始化文件,主要为系统提供初始化服务,在系统启动时将被系统所访问,并根据其所保存的参数值对系统进行配置。Windows专门提供了三个API函数GetProfileInt()、GetProfileString()和WriteProfileString()对Win.ini进行读写访问,其函数用法同访问私有初始化文件的那几个函数非常类似,只是不必再去指定初始化文件名。下面是这三个函数的原型声明:
UINT GetProfileInt(LPCTSTR lpAppName, // 节名地址
LPCTSTR lpKeyName, // 项名地址
INT nDefault // 在项名没有找到时返回的缺省值
);
DWORD GetProfileString(LPCTSTR lpAppName, // 节名地址
LPCTSTR lpKeyName, // 项名地址
LPCTSTR lpDefault, // 缺省字符串地址
LPTSTR lpReturnedString, // 存放字符串的缓存的地址
DWORD nSize // 缓存的大小
);
BOOL WriteProfileString(LPCTSTR lpAppName, // 节名地址
LPCTSTR lpKeyName, // 项名地址
LPCTSTR lpString // 要写入字符串的地址
);
只要对前面对私有初始化文件进行访问的代码稍加改动即可将程序的配置信息添加到Win.ini中,改动后的代码如下:
// 得到程序累计运行次数
UINT Time = GetProfileInt("PROGRAM", "RUNTIME", 0);
// 得到上次运行日期
GetProfileString("DATE", "LAST", "2002-11-1", buffer, 1000);
// 显示从初始化文件获取到的文件信息
sMsg.Format("本软件共运行过%d次,上次运行日期为%s", Time, CString(buffer));
AfxMessageBox(sMsg);
// 累加运行次数,并保存到初始化文件
Time++;
sTime.Format("%d", Time);
WriteProfileString("PROGRAM", "RUNTIME", sTime);
// 获取当前日期,并保存到初始化文件
CTime tm = CTime::GetCurrentTime();
sDate.Format("%d-%d-%d", tm.GetYear(), tm.GetMonth(), tm.GetDay());
WriteProfileString("DATE", "LAST", sDate);
由于Win.ini文件是系统初始化文件,在程序没有运行前文件内不含“DATE”和“PROGRAM”等自定义的节以及其下各项,因此在程序第一次执行后,将由WriteProfileString()函数向Win.ini文件末尾创建相关节、项,并完成数据的写入。
对系统注册表的访问
初始化文件在早期Windows编程中使用非常普遍,各种系统初始化文件如Win.ini、System.ini等甚至还担负了对系统软、硬件配置以及用户环境等进行控制的重任。在目前的Windows编程中,虽然初始化文件还以其方便简洁的编程方法而继续使用,但其使用范围已大不如前,尤其是在为系统提供配置信息等方面的功能被大大削弱,几乎不起什么重要作用。取而代之的是一种被称为“系统注册表”的二进制数据文件,为应用程序和系统的组成部分提供存储和检索相关的配置信息。该文件只能通过系统提供的注册表编辑器(Registry Editor)进行编辑,或是在程序中通过专门用于注册表访问的API函数对其进行编辑。
系统注册表是一个多层次的结构树,在树的根部共有六个预定义键:HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、KEYI_USERS、HKEY_CURRENT_CONFIG和HKEY_DYN_DATA(HKEY_DYN_DATA键只对于Windows 9x而言)。在每一个预定义键下面还包含有众多的树节点,每一个节点都是注册表的关键字,均代表了一个特定的配置项目。在节点展开后又包含有子关键字,直至最后的节点。其中HKEY_CLASSES_ROOT键主要保存了文档类型和属性等信息以及同应用程序相关的分类信息等。HKEY_CURRENT_USER键主要对用户的当前系统配置进行记录。HKEY_LOCAL_MACHINE键对计算机的状态信息进行记录。KEYI_USERS键对当前系统的所有用户信息进行组织。HKEY_CURRENT_CONFIG和HKEY_DYN_DATA键则分别对硬件配置信息和同动态注册相关的数据信息进行记录。
Windows提供了近30个API函数用于访问系统注册表,这些API函数提供了对注册表进行键的创建、打开、关闭、删除和对键值的设置、删除等功能。通常对注册表比较常用的操作不外乎对键或键值的添加、删除与修改等,而注册表中的各个键均有其特定的作用,通过对这些键的访问和对键值的适当修改可以获取到几乎所有的同系统有关的软、硬件信息并可对系统性能进行优化。例如,有关用户的信息位于系统注册表的HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\下(对于Windows 2000 Professional而言),键值名RegisteredOwner和RegisteredOrganization分别表示用户的姓名和公司名称。如需要在程序中获取该信息,只要访问此键值的内容即可。
读取注册表中某个键值的内容首先要通过RegOpenKey()或RegOpenKeyEx()函数打开相应的键,然后再调用RegQueryValue()或RegQueryValueEx()检索指定键值的内容,操作完成后调用RegClosefKey()将打开的键关闭,结束对注册表的访问。其中RegOpenKeyEx()和RegQueryValueEx()的功能比较强大,分别是对RegOpenKey()和RegQueryValue()在功能上的扩展,其函数原型为:
LONG RegOpenKeyEx(HKEY hKey, // 待打开的预定义键
LPCTSTR lpSubKey, // 待打开的子键的地址
DWORD ulOptions, // 保留
REGSAM samDesired, // 安全访问掩码
PHKEY phkResult // 打开的键的地址
);
LONG RegQueryValueEx(HKEY hKey, // 待检索的键
LPTSTR lpValueName, // 要检索的键值名称的地址
LPDWORD lpReserved, // 保留
LPDWORD lpType, // 键值类型的地址
LPBYTE lpData, // 存放检索结果的缓存的地址
LPDWORD lpcbData // 缓存长度的地址
);
最后,给出了通过访问注册表键值而得到用户注册信息的简单程序示例,该示例片段展示了对系统注册表指定键的打开、检索以及关闭等基本处理过程:
// 打开键
HKEY hKEY;
LPCTSTR Rgspath = "Software\\Microsoft\\Windows NT\\CurrentVersion";
LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, Rgspath, 0, KEY_READ, &hKEY);
if(ret != ERROR_SUCCESS)
{
RegCloseKey(hKEY);
return;
}
// 读取键值内容
DWORD dwInfoSize;
DWORD type = REG_SZ;
BYTE UserInfo[255];
ret = RegQueryValueEx(hKEY, "RegisteredOwner", NULL, &type, UserInfo, &dwInfoSize);
if(ret!=ERROR_SUCCESS)
{
RegCloseKey(hKEY);
return;
}
……
// 关闭键
RegCloseKey(hKEY);
注册表键的访问权限
基于注册表在Windows操作系统中的重要地位和所起的特殊作用,非常有必要对其进行一些安全性方面的设置。虽然可以通过设置用户权限来限制对注册表中敏感数据的访问,但该由该用户所使用的应用程序却很有可能必须访问此数据。这就需要能在程序中对注册表键的安全性级别进行修改。如在使用RegOpenKeyEx()打开某个键时,可用WRITE_OWNER访问权限打开,并将返回的指向注册表的句柄传递给对RegSetKeySecurity()的调用,以此取得对键的所有权:
RegOpenKeyEx(HKEY_CLASSES_ROOT, “TestValue”, 0, WRITE_OWNER, &hKey);
RegSetKeySecurity(hKey, OWNER_SECURITY_INFORMATION, &Security);
其中,Security是SECURITY_DESCRIPTOR结构的一个对象。除上面使用的WRITE_OWNER之外,对注册表键的访问权限还有DELETE、READ_CONTROL、WRITE_DAC等标准访问权限以及注册表所专有的访问权限KEY_CREATE_LINK、KEY_CREATE_SUB_KEY、KEY_EXECUTE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFY、KEY_QUERY_VALUE、KEY_SETVALUE、KEY_ALL_ACCESS、KEY_READ和KEY_WRITE等。
小结
在应用程序中使用初始化文件和注册表将可以完成许多特殊的功能,通常应用较多的是用来记录和获取程序在上一次运行的状态配置,使程序具有“记忆”功能。而有些黑客软件也同样是通过向初始化文件和注册表写入某些特定信息而使其具有开机运行的功能。 |