第四天 面向对象.docx
- 文档编号:12028659
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:41
- 大小:838.20KB
第四天 面向对象.docx
《第四天 面向对象.docx》由会员分享,可在线阅读,更多相关《第四天 面向对象.docx(41页珍藏版)》请在冰豆网上搜索。
第四天面向对象
第四天面向对象_03
3.1、static关键字(重点)
这个关键字一直在见到,从未被真正使用过,而在Java中,static关键字可以用于定义属性及方法。
3.1.1 、使用static定义属性
在讲解static定义属性操作之前,首先编写如下的一道程序。
范例:
现在定义一个表示北京人的操作类,所有人所在的城市都是北京
classPerson{
privateStringname;
privateintage;
Stringcountry="北京"; // 此处暂时不封装
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringgetInfo(){
return"姓名:
"+this.name+",年龄:
"+this.age+",城市:
"+this.country;
}
}
publicclassTestDemo{
publicstaticvoidmain(Stringargs[]){
Personper1=newPerson("张三",20);
Personper2=newPerson("李四",21);
Personper3=newPerson("王五",22);
System.out.println(per1.getInfo());
System.out.println(per2.getInfo());
System.out.println(per3.getInfo());
}
}
那么,以上的程序,现在的内存分配图如下。
很明显,现在不管有多少个Person对象,那么所有的country属性都应该是相同的内容,那么现在请思考一下,如果有一天时光穿越了,北京变为燕京了,这个时候如果Person类已经有了5000W个对象产生了,你认为此时的代价是什么?
5000W个Person对象都需要修改country的内容,那么如果按照修改一个对象的country属性内容要花费1ms来计算,那么5000W个对象的修改时间是:
50000S= 很多分钟,那么现在就可以发现问题:
· country属性应该是一个公共的内容,但是以上代码是将其分配给了每一个对象;
· 对country属性维护的时候要考虑的对象太多了,也不方便。
所以,如果要想将country与普通属性相区分,并且表示公共的概念,则应该使用static关键字完成。
classPerson{
privateStringname;
privateintage;
staticStringcountry="北京"; // 此处暂时不封装
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringgetInfo(){
return"姓名:
"+this.name+",年龄:
"+this.age+",城市:
"+this.country;
}
}
publicclassTestDemo{
publicstaticvoidmain(Stringargs[]){
Personper1=newPerson("张三",20);
Personper2=newPerson("李四",21);
Personper3=newPerson("王五",22);
per1.country="燕京";
System.out.println(per1.getInfo());
System.out.println(per2.getInfo());
System.out.println(per3.getInfo());
}
}
那么,现在一个对象对country属性所做的修改,一定会影响到其他对象,但是这里有一个问题了,既然使用了static定义的属性表示的是公共属性,那么如果现在由某一个对象修改是不合适的,应该由所有对象的集合的最大代表,就是类了,即:
static属性最好的调用,是通过“类名称.static属性”的方式来完成。
Person.country="燕京"; // 类.static属性
通过本程序,就应该清楚以下几点:
· 使用static定义的属性不在堆内存之中保存,保存在全局数据区;
· 使用static定义的属性表示类属性,类属性可以由类名称直接进行调用;
· static属性虽然定义在了类之中,但是其可以在没有实例化对象的时候进行调用(普通属性保存在堆内存里,而static属性保存在全局数据区之中);
提示:
在以后的开发之中,首先想到的不是static属性,就是普通属性。
3.1.2 、使用static定义方法
除了使用static定义属性之外,方法上也可以使用static进行定义,那么很明显,使用static定义的方法也可以在没有实例化对象产生的情况下由类名称直接进行调用。
classPerson{
privateStringname;
privateintage;
privatestaticStringcountry="北京"; // 此处暂时不封装
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicstaticvoidsetCountry(Stringc){
country=c;
}
publicstaticStringgetCountry(){
returncountry;
}
publicStringgetInfo(){
return"姓名:
"+this.name+",年龄:
"+this.age+",城市:
"+this.country;
}
}
publicclassTestDemo{
publicstaticvoidmain(Stringargs[]){
Person.setCountry("燕京"); // 类.static方法()
System.out.println(Person.getCountry());
Personper1=newPerson("张三",20);
System.out.println(per1.getInfo());
}
}
以上的代码如果单独观察应该都不难理解,主要都是由于static定义的特殊性所决定的,但是现在的类之中就比较热闹了,因为分成了两派:
static派、非static派,而对于方法的操作有如下两个定义:
· static定义的方法不能调用非static的方法或属性;
· 非static定义的方法可以调用static的属性或方法。
讨论:
为什么要有这样的限制呢?
· 使用static定义的属性和方法,可以在没有实例化对象的时候使用;
· 非static定义的属性和方法,必须实例化对象之后才可以进行调用。
3.1.3 、主方法
在讲解主方法之前,首先来思考一下小小的区别:
在之前讲解Java方法定义的格式给过以下格式:
如果一个方法在主类之中定义,并且由主方法直接调用的时候,那么前面必须有publicstatic。
publicstatic 返回值类型 方法名称 (参数列表){
[return[返回值];]
}
范例:
观察代码
publicclassTestDemo{
public static voidmain(Stringargs[]){
print(); // 直接调用
}
public static voidprint(){
System.out.println("HelloWorld.");
}
}
按照之前所学习的概念来讲,此时,表示的是一个static方法调用其他的static方法,但是如果这个时候的print()方法上没有static呢?
所有的非static方法几乎都有一个特点:
方法要由实例化对象调用。
publicclassTestDemo{
publicstaticvoidmain(Stringargs[]){
newTestDemo().print(); // 对象调用
}
publicvoidprint(){ // 非static方法
System.out.println("HelloWorld.");
}
}
那么现在继续来观察主方法的组成,可以发现里面有很多的关键字:
· public:
是一种访问权限,表示公共;
· static:
此方法由类名称直接调用,执行类:
java 类名称;
· void:
主方法是一切的开始,开弓没有回头箭;
· main:
系统规定的一个方法名称,执行类的时候默认找到此名称;
· Stringargs[]:
表示的是一些运行时参数,通过字符串接收。
范例:
接收参数
publicclassTestDemo{
publicstaticvoidmain(Stringargs[]){
for(intx=0;x System.out.println(args[x]); } } } 所有的属性在执行类的时候使用空格分隔,例如: javaTestDemo 参数 参数 参数 … 但是,由于在默认情况下空格作为参数的分隔符,那么如果说现在要输入的参数本身就存在空格呢? 那么这些参数上可以使用“"”声明: javaTestDemo"helloworld""hellomldn"。 3.1.4 、static关键字的使用 在实际的工作之中,使用static的原因有二: · 希望可以在没有实例化对象的时候可以轻松的执行类的某些操作; · 现在希望表示出数据共享的概念。 范例: 统计一个类产生的实例化对象个数 一个类肯定可以有多个实例化对象产生,那么现在希望增加一个统计操作,可以统计出一个类之中的所产生的实例化对象的个数。 如果现在要产生新的实例化对象,则一定会调用类中的构造方法,所以可以在构造方法中增加统计,而且这个统计的变量,应该是所有对象共享的,那么应该将其定义为static属性。 classPerson{ privatestaticintcount=0; publicPerson(){ // 构造方法一定会调用 System.out.println("对象个数: "+++count); } } publicclassTestDemo{ publicstaticvoidmain(Stringargs[]){ newPerson();newPerson();newPerson(); } } 范例: 为类的属性自动命名 例如,在一个类之中可能会有多个构造方法,那么假设类之中存在了一个name属性,要求这个属性一定要有内容,即: 如果用户调用了无参构造方法,那么name也需要有一个具体的内容出现,所以这个时候就可以利用static完成。 classBook{ privatestaticintcount=0; privateStringtitle; publicBook(){ // 自动命名 this("NOTITLE-"+count++); } publicBook(Stringtitle){ this.title=title; } publicStringgetTitle(){ returnthis.title; } } publicclassTestDemo{ publicstaticvoidmain(Stringargs[]){ System.out.println(newBook().getTitle()); System.out.println(newBook("JavaSE").getTitle()); System.out.println(newBook().getTitle()); }} 以上的两个代码只是为了说明static声明变量的特点,实际之中基本上很少去这样使用,不过如果出现了类似的应用,应该能够反应出来其实现的基本原理。 3.2、代码块(了解) 代码块是在程序之中使用“{}”定义起来的一段程序,而根据代码块声明位置以及声明关键字的不同,代码块一共分为四种: 普通代码块、构造块、静态块、同步块(暂时不讲解)。 3.2.1 、普通代码块 普通代码块是定义在方法之中的代码块,在讲解此操作之前,首先来观察以下代码。 publicclassTestDemo{ publicstaticvoidmain(Stringargs[]){ if(true){ intx=10; // 局部变量 System.out.println("x="+x); } intx=100; // 全局变量 System.out.println("x="+x); } } 普通代码块就是if取消。 publicclassTestDemo{ publicstaticvoidmain(Stringargs[]){ { // 普通代码块 intx=10; // 局部变量 System.out.println("x="+x); } intx=100; // 全局变量 System.out.println("x="+x); } } 几乎用不到的,知道就行了。 3.2.2 、构造块 普通代码块是定义在方法之中的,而构造块是定义在类之中的代码块。 classPerson{ publicPerson(){ System.out.println("构造方法。 "); } { // 构造块 System.out.println("构造块。 "); } } publicclassTestDemo{ publicstaticvoidmain(Stringargs[]){ newPerson(); newPerson(); newPerson(); } } 可以发现,构造块优先于构造方法执行,而且每当有一个新的实例化对象产生的时候,就会出现构造块的执行。 3.2.3 、静态块 静态块也是定义在类之中的,如果一个构造块上使用了static关键字进行定义的话,那么就表示静态块,但是静态块要考虑两种情况: 情况一: 在非主类之中定义的静态块 classPerson{ publicPerson(){ System.out.println("构造方法。 "); } { // 构造块 System.out.println("构造块。 "); } static{ System.out.println("静态块。 "); } } publicclassTestDemo{ publicstaticvoidmain(Stringargs[]){ newPerson(); newPerson(); newPerson(); } } 可以发现,静态块优先于构造块执行,而且不管有多少个实例化对象产生,静态块只调用一次。 情况二: 在主类中定义的静态块 publicclassTestDemo{ static{ System.out.println("静态块。 "); } publicstaticvoidmain(Stringargs[]){ System.out.println("HelloWorld."); } } 在主类之中的静态块优先于主方法执行。 那么既然有静态块有这个特点,实际上就可以简单的修改一下。 有意思的操作: 不使用主方法输出“HelloWorld.”,彻底终结了 publicclassTestDemo{ static{ System.out.println("HelloWorld."); System.exit (1); } } 以上代码在JDK1.7之前都可以正常使用,JDK1.7之后完蛋了,bug终于解决。 3.3、思考题 要求完成一个系统的登陆程序,通过初始化参数输入用户名和密码,如果用户名是“mldn”,密码是“hello”,则显示欢迎光临的信息,如果不是则显示“登陆失败”的信息。 设计的时候多考虑一下类的组成结构,以及可能出现的问题。 如果说
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第四天 面向对象 第四 面向 对象