Java基础:面向对象
2015-04-28 15:27
183 查看
第一部分:面向对象的基础
一、面向对象的概念
理解面向对象:
1)面向对象是相对面向过程而言。
2)面向对象和面向过程都是一种思想。
3)面向过程强调的是功能行为。
4)面向对象是将功能封装进对象,强调具备功能的对象。
5)面向对象是基于面向过程的。
实例:将大象装进冰箱里面。
面向过程:把大象装进冰箱里。
(a)打开冰箱
(b)装入大象
(c)关闭冰箱
面向过程注重的是打开、存储与关闭的功能行为。
面向对象:
打开、存储与关闭均是冰箱这类事物对应的行为,因为操作的都是冰箱。因此可以将这些动作定义到冰箱当中,冰箱是一个实实在在存在的东西,称之为对象。而现在看到的不再是打开、存储与关闭,而是冰箱,冰箱中定义了打开、存储与关闭的动作。
图解:
总结:
1、面向过程是一种思想。C语言就是面向过程的语言。
2、面向对象的出现将复杂的事情简单化,面向过程需要面对多个动作,而现在只需要面对一个对象即可。
上图中左边需要从头到尾执行这些动作,而到了右边找到冰箱,让冰箱去打开、关闭和存储就可以了。角色由之前的执行者变成了指挥者(指挥对象做事情)。
面向过程是面向对象的基础,面向对象基于面向过程。
3、面向对象的思想落实到程序:
写程序时不是先定义功能,而是先面向对象,对象需要什么功能就就该功能定义到对象中去,封装好了之后下次若要使用该功能,则只要找到该对象,功能就有了。
开发时先找Java中是不是已经提供了相对性的对象,若有,则直接拿来使用;若没有,则再定义。
(找对象,建对象,用对象,并维护对象之间的关系)
在Java中,一切皆对象。
面向对象的三个特征:封装、继承和多态
二、类与对象的关系
类就是对现实生活中事物的描述,描述事物就是描述事物的属性和行为(属性对应类中的变量,行为对应类中的方法)。
对象就是这类事物实实在在存在的个体。
映射到Java中:
描述:就是class定义的类。
对象:就是对应Java在堆内存中通过new操作符产生的实体。(数据多了用对象存)
示例:对汽车进行描述
可以理解为类就是图纸,汽车就是堆内存中的实体。
内存中的体现:
对象的特点:封装数据,数据包括属性和行为(属性与行为统称为类中的成员,成员变量、成员函数)。
4000
操作对象:对象.对象成员
注意:
1)描述事物的类没有主函数,因为该类不需要独立运行,若想使用该类中封装的属性和功能,直接建立该类对象,随时都可以使用。
2)变量定义在了函数的外面,称之为成员变量。
成员变量与局部变量:
1)局部变量作用于函数或for循环中,并且存在于栈内存中,没有默认初始化值。
2)成员变量作用于整个类中,因为对象的存在而存在与堆内存中,有默认初始化值。(静态成员存在与方法区中)
匿名对象:
1、匿名对象是对象的简化形式。
2、匿名对象的两种使用情况。
1)对象的方法只调用一次。(若对一个对象进行多个成员调用,必须给该对象起名)
2)调用函数/功能时作为实际参数传递。
示例:
第一句代码一执行完毕就变成垃圾,因为没有被使用。第二句话同样如此。
第三局代码有意义,因为调用的是方法,方法中有方法体,可以有运行内容在里面。
因此,匿名对象调用属性无意义,调用方法有意义,有时还可以简化代码。
三、封装
1、概念
封装,是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
2、封装的好处
1)将变化隔离。(属性如何变化和对象没关系)
2)便于使用。(不用了解内部构造)
3)提高重用性。
4)提高安全性。
函数是Java中最小的封装体。
3、关键字private
private:权限修饰符,用于修饰类中的成员(成员变量与成员方法)。私有后成员仅在本类中有效,外界无法直接访问。
对私有的成员变量一般都会提供相对性的两个访问方式set,get。(可以对外界输入的属性进行逻辑判断)
示例代码:
输出结果为 :
注意:
1)封装不是私有,私有仅仅是封装的一种表现形式,不私有也能实现封装。(不同包中的默认权限也是一种封装形式)
2)私有是最小权限。
四、构造函数
1、特点
1)函数名与类名相同。
2)不用定义返回值类型。(与void不一样)
3)不可以写return语句。
2、作用
给对象进行初始化。
对象一建立就会调用与之相对应的构造函进行初始化。当一个类中没有构造函数时,系统会默认给该类加一个空参数的构造函数,方便该类进行初始化。
当类中自定义了构造函数后,默认的构造函数就消失了。此时若要建立该类对象,则必须访问指定的构造函数以进行初始化,否则会发生错误。
构造函数与一般函数的区别:
1)写法不同。构造函数名与类名相同。
2)运行上的不同。构造函数在对象一建立时就会运行,对对象进行初始化。一般方法是对象调用才执行,是给对象添加具备的功能。
3)同一个对象,构造函数只运行一次,而一般方法可以被该对象调用多次。
什么时候使用构造函数?
当分析事物时,该事物就具备了一些特性/行为,那么将这些内容定义在构造函数中。(如果构造函数中有未知内容参与运算,则定义参数)
注意:
构造函数可以被私有化(private),但此后无法在外部建立与之相对应的对象;若一个类中所有的构造函数都被私有化,则该类无法在外部建立对象,因为所有的对象都不能进行初始化动作。
3、构造代码块
1)作用:给所有对象进行初始化。(对象一建立就运行,而且优先于构造函数执行)
2)与构造函数的区别:
构造代码块是给所有对象进行统一初始化的,而构造函数是给对应的对象进行初始化的。
示例:
结果为:
五、this关键字
1、含义
this代表它所在函数所属对象的引用。即:哪个对象在调用this所在函数,this就代表哪个对象。
类里面的成员被使用完全也是由对象完成的。(省略了this.)
2、this的应用:
当定义类中的功能时,该函数内部要调用到该函数所属的对象时,用this来代替这个对象。但凡本类功能内部使用了本类对象,都用this来表示。
3、构造函数之间的调用
示例:
注意:
1)this语句只能用在构造函数的第一行。(初始化的动作要先执行,如果初始化中还有初始化,就先执行更细节的初始化)
2)一般函数是不能直接调用构造函数的,因为this语句只能用于构造函数间的相互调用,不能用于一般函数中。
六、static关键字
1、static(静态)
static:是一个修饰符,用于修饰类中的成员(包括成员变量、成员方法,不能修饰局部变量)。被static修饰后,成员变量就不在堆内存中了,而是被单独提取出来,存放在方法区中,每个对象都可以访问。(方法区中存放的是类中的方法以及类中的共享数据)
示例:
1)被static修饰后的成员具备的特点:
(a)随着类的加载而加载。
当Person类被使用时,会被加载到内存中,而此时,静态成员country就已经存在了。Person类只要还在,静态成员就会一直存在于内存中,直至类在内存中消失。
(b)优先于对象存在。
Person类加载进内存中时,静态成员counrty就存在与内存中,而非静态成员name不存在,因为name只有在对象建立时才会存在于堆内存中。当对象建立并使用完毕后,name变不存在于堆内存中,而country依然存在。
(c)被所有对象所共享。
(d)可以直接被类名调用。(调用格式:类名.静态成员)
2)实例变量(对象变量/非静态变量)与类变量(静态变量)的区别
(a)存放位置
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
(b)生命周期
类变量的生命周期最长,随着类的消失而消失。
实例变量的随着对象的消失而消失。
3)静态使用时的注意事项
(a)静态方法只能访问静态成员。(非静态方法既可以访问非静态成员又可以访问静态成员)
(b)静态方法中不可以定义this,super关键字。(因为静态优先于对象存在,this,super代表的是对象)
(c)何时使用静态:
静态分静态方法和静态成员:
当对象中出现共享数据时,该数据被静态所修饰。但对象特有的数据要定义成非静态存放于堆内存中。
当功能内部没有访问到非静态数据(对象特有数据)时,可以将该功能定义成静态的。
4)静态的利弊
利:对对象的共享数据进行单独存储,节省内存;可以直接被类名调用。
弊:生命周期过长;出现访问局限性(静态虽好,却只能访问静态)。因此不建议定义过多的静态成员。
2、main函数
主函数是静态的。
public static void main(String[] args)
含义:
public 代表该函数的访问权限是最大的。
static 代表该函数随着类的加载就已经存在了。
void 代表主函数没有具体的返回值。
main 不是关键字,但是是一个特殊的单词,能被JVM识别。
String[] args 主函数的参数,参数类型是一个字符串数组。
主函数是固定格式的,能被JVM识别,唯一能改变的就是参数名args;JVM在调用主函数是,传入的是new String[0]。可以在启动JVM时给主函数传递一些参数,格式如下:
java MainDemo zhang lisi
java 启动虚拟机
MainDemo 需要执行的类
zhang lisi 给MainDemo的主函数传递的参数
3、生成帮助文档
当类中的成员都是静态成员时,该类就是一个工具类。为方便其他程序员使用该类中的功能,需要生成帮助文档,Java中提供了这样的工具:javadoc。(DOS命令行)操作格式如下:
javadoc -d c:\myhelp -author -version ArrayTool
javadoc 启动文档生成工具
-d c:\myhelp 文档存放目录为c:\myhelp
-author -version 文档中包括做作者和版本
注意:
1、要用javadoc工具生成文档时,该类要加public的权限修饰符。
2、需要生成帮助文档的成员前要用/** */在java源文件中注释好,而且其只提取被public修饰的成员前的注释文档。
3、文档注释中的特殊标识:
@author 作者
@version 版本
@param 参数
@return 返回值
示例:
4、静态代码块
1)格式:
static
{
执行语句;
}
2)静态代码块的特点
(a)随着类的加载而执行,只执行一次,并优先于构造函数执行。
(b)用于给类进行初始化。
一个类中可以有多个静态代码块和构造代码块。
5、对象的初始化过程
Person p = new Person("zhangsan",20);
这句话在内存中完成了以下8个动作:
1)因为new用到了Person.class,所以会先将Person.class加载到内存中。
2)执行类中的静态代码块,给Person.class进行初始化。(如果静态代码块存在)
3)在堆内存中开辟空间,分配内存地址值。
4)在堆内存中建立对象的特有数据,并进行默认初始化。(null,0)
5)对属性进行显示初始化。
6)对对象进行构造代码块初始化。
7)对对象进行与之对应的构造函数初始化。
8)将内存地址值赋给栈内存中的p变量。
6、对象调用成员过程。
Person类中所有方法都存在与方法区。
图例:
七、单例设计模式
设计模式:早期在建筑领域出现的概念,也就是总结得一些经验与方法,模式的出现让问题变得更简单。
Java中一共有23种设计模式,下面介绍单例设计模式。
单例设计模式:解决一个类在内存中只存在一个对象的方案。
步骤:
1)将构造函数私有化,禁止外部其他类建立对象。
2)在本类中创建一个本类对象。
3)提供一个公共方法以获取到本类对象。
单例设计模式有有两种实现方式:
1、饿汉式
对象一加载,方法区就存在就有s,堆内存中就有对象。
2、懒汉式
对象的延时加载。(类一加载s为空,且堆内存中还没有对象,只有调用方法的时候才建立对象。
懒汉式的特点及存在的问题:
1)对象的延时加载。
2)延时加载在多线程访问时存在安全问题。
3)为解决多线程访问的安全的问题,加入同步synchronized,且其锁是该类对应的字节码文件对象。
4)加入同步之后会存在效率低的问题,因此加入双重判断语句。
饿汉式图解:
第二部分:面向对象的特点及其他
一、继承
1、继承的概述
继承是面向对象的第二个特征。当多个类中出现共性功能时,将功能向上进行抽取,定义在父类中,让子类继承父类。父类中的功能子类可以直接继承、使用。
注意:千万不要不要为了获取其他类的功能而继承,必须是类与类之间有关系。(用关键字extends申明两个类之间的关系)
2、继承的特点
1)提高了代码的复用性。
2)继承的出现让类与类之间产生了关系,有了这个关系才有了多态的特性。
Java语言中:只支持单继承,不支持多继承,因为多继承容易带来完全隐患。(即一个类中只要继承了一个类就不可以继承其他类)。但是Java保留了这种机制,并用另一种体现形式来表示,即多实现。同时,Java也支持多层继承。
如何使用一个继承体系中的功能呢?
想要使用体系,先查阅父类中的功能,因为父类中定义的是该体系中的共性内容,通过了解共性内容就可以知道该体系的基本功能。查阅到父类功能后,建立子类对象去使用这些功能。因为有可能父类不能创建对象(抽象类等),创建子类对象可以使用子类中的特有功能。(查阅父类功能,创建子类对象使用功能)
3、子父类中成员变量的特点。
(a)super关键字:代表父类对象的引用。super的使用与this的使用基本一致。(this关键字代表本类对象的引用)
(b)如果子父类中出现了非私有的同名变量时,子类要访问本类中的变量用this,子类要访问父类中的变量,用super。
4、函数覆盖(子父类中函数的特点)
当子类出现和父类一模一样的函数时,若子类要调用该函数,会运行子类对象的内容,如同父类的函数被覆盖一下。这就是函数的另一个特性,覆盖。(父类依然存在,只是没有运行)
当子类继承了父类,沿袭了父类的功能到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时没有必要定义新功能而是使用覆盖特性,保留覆盖的功能,并重写功能的内容。
示例代码:
函数覆盖时注意事项:
1)子类覆盖父类,必须保证子类权限大于或等于父类权限,才可以覆盖,否则编译失败。
2)静态只能覆盖静态。
函数重载与覆盖的区别:
1)重载:只看函数的参数列表。
2)重写:子父类方法要一模一样(包括参数列表,返回值类型与函数名)。
以下两种情况不是覆盖:
父类:private void show()
子类:public void show() 子类不知道父类有该功能
父类:int show()
子类:void show() 编译错误,因返回值类型不同
5、子类的实例化过程(子父类构造函数的特点)
在子类对象进行初始化时,父类的构造函数也会运行,那是因为子类构造函数第一行有一条隐式语句super()会访问父类中空参数的构造函数,而且子类所有的构造函数默认第一行都是super()。
为何子类一定要访问父类中的构造函数?
因为父类中的数据子类可以直接获取,子类对象在建立时需要先查看父类是如何对这些数据进行初始化的,所以子类在进行初始化时会访问父类中构造函数,具体访问哪一个可以用super语句去指定。子类构造函数的第一行也可以手动指定this语句去访问本类中的构造函数,但必须要有一个构造函数访问父类中的构造函数。
示例代码:
6、final关键字
1)final可以修饰类、函数及变量。
2)被final修饰的类不可以被继承,以避免该类被继承,功能被复写后产生问题。(如,直接操作虚拟机的类)
3)被final修饰的方法不可以被复写。
4)被final修饰的变量是一个常量,只能赋值一次。
作为常量,书写时所有字母都大写,多个单词组成时中间加”_“连接。
全局常量:如 public static final double PI = 3.14;
5)内部类定义在局部位置上时,只能访问该局部被final修饰的成员。
7、抽象类
当多个类中出现相同功能,当功能主体不同,这时可以进行向上进行抽取,只抽取功能主体,不抽取功能定义。
抽象类的特点:
1)抽象方法一定定义在抽象类中。
2)抽象方法和抽象类必须被abstract修饰。
3)抽象类不可以new对象,因为抽象方法调用无意义。
4)抽象类中的方法要被调用,必须由子类复写所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。但抽象类中可以有非抽象方法。
抽象类与一般类的区别:
抽象类与一般类并无太大区别,该如何描述事物就如何描述事物,只不过该事物出现了一些看不懂的东西,这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体,故将其通过抽象方法表示。
抽象类比一般类多个个抽象方法,故抽象类不可以实例化。
8、Objdect类
Object是Java中所有类的父类(或超类),所有对象(包括数组)都继承这个类的方法。
常用方法:
boolean equals(Object obj) 判断两个对象是否相等,子类不复写则判断的是哈希值是否相等)
int hashCode() 返回对象的内存地址值,哈希值
String toString() 返回对象的字符串表示形式,getClass().getName()+"@"+Integer.toHexString(hashCode())
Class<?> getClass() 返回该类所对应的字节码文件对象
多线程中的常用方法(Object类中):
void wait() 当前线程等待
void notify() 唤醒线程池中的第一个线程
void notifyAll() 唤醒线程池中的所有线程
二、模板方法模式
模板方法模式就是在定义功能时,功能的一部分是确定的,另一部分是不确定的,但是确定的部分在使用不确定的部分,那么就将不确定的部分暴露出去,由子类复写来完成。(不确定的部分可以定义成抽象方法,确定的部分可以加final修饰)
示例代码:
结果为:
三、接口(interface)
1、定义
接口是一个特殊的抽象类,类中的方法都是抽象的,变量都是常量。Java中用关键字class来定义类,用interface来定义接口。
2、接口的格式
1)接口中常见定义:常量,抽象方法。
2)接口中成员修饰符都是固定的。(若忘记写了,系统会自动补齐)
成员常量:public static final
成员方法:public abstract
3、继承与实现的区别
类与类之间的关系:extends(父类有非抽象方法可以给子类使用)
类与接口之间的关系:implements(接口中的方法都是抽象方法,子类若想实现则需全部复写,接口也不可以直接创建对象。
接口与接口之间的关系:extends
4、多实现
1)接口可以被多实现,这也是java对多继承不支持的转换形式。
2)在Java中,一个类可以在继承一个类的同时实现多个接口。
3)接口与接口之间可以多继承。(因为都是抽象方法,没有方法体)
5、接口的特点:
1)接口是对外暴露的规则。
2)接口时程序功能的扩展。
3)接口降低了程序之间的耦合性。
四、多态
1、多态的基本体现
父类引用指向子类对象。(父类引用接收子类对象)
示例代码:
2、多态的好处
提高了程序的扩展性。
3、多态的前提
必须是类与类之间有关系,继承或实现。(通常还有一个前提,就是存在覆盖)
4、多态的弊端
只能使用父类引用访问父类成员。
如想访问子类中特有的方法,则应该进行类型转换,如:
Cat c = (Cat)a1;
c.catchMouse();
千万不要出现将父类对象转换成子类类型。如:
Animal a = new Animal();
Cat cat = (Cat)a;//报错,类型转换异常
新关键字:instanceof 判断某一类型的指向是否符合指定类型。
如:boolean flag = a instanceof Cat,判断a的引用是否指向Cat类型。
5、多态使用中的注意事项
1)在多态中,非静态成员函数的特点:编译看左边,运行看右边。
2)在多态中,成员变量的特点:无论编译和运行,都看左边。(针对重名的请况)
3)在多态中,静态成员函数的特点:无论编译运行,都看左边。
6、多态的应用
示例代码:
运行结果:
图例:
五、内部类
将一个类定义在另一个类的里面,里面的那个类就称为内部类(内置类或嵌套类)。
示例代码:
1、访问特点
1)内部类可以直接访问外部类中的成员,包括私有成员。(持有一个引用:外部内名.this)
2)外部类要访问内部类中的成员则必须建立内部类对象。
2、访问格式
1)当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,直接建立内部类对象。格式为:
外部类名.内部类名 变量名 = 外部类对象。内部类对象
Outer.Inner inner = new Outer().new Inner();
2)当内部类定义在外部类成员位置上时,可以被成员修饰符修饰,如:
private:将内部类在外部类中进行封装
static:内部类具备了静态的特性
3、内部类使用的注意事项
1)当内部类被static修饰时,只能访问外部类中被static修饰的成员
在外部其他类中,访问静态内部类中的非静态成员:new Outer.StaticInner().function();(通过内部类对象进行访问)
在外部其他类中,访问静态内部类中的静态成员:Outer.StaticInner.method();(都是静态的, 可以直接被类名调用)
2)当内部类中定义了静态成员,该内部类必须是静态的。
3)当外部类中的静态成员访问到内部类时,该内部类也必须是静态的。
4)当内部类在局部位置时,使用时要注意以下两点:
(a)不能被成员修饰符private,static等修饰。
(b)可以直接访问外部类中的成员,因为还只有外部类的引用(外部类名.this),但是只能访问它所在局部中被final修饰的局部变量。
何时使用内部类?
当描述事物时,事物的内部还有事物,内部事物就用内部类来描述。
4、匿名内部类
1)匿名内部类其实就是内部类的简写格式。
2)定义匿名内部类的前提:内部类必须是继承一个类或实现接口。
3)匿名内部类的格式:
new 父类名或接口名(构造函数的参数)
{
定义子类内容;(一般是复写父类中的方法)
}
4)其实内部类就是一个匿名子类对象,只是将定义类和建立对象封装成了一个整体。
5)匿名内部中定义的方法最好不要超过3个。
示例代码:
运行结果:
一、面向对象的概念
理解面向对象:
1)面向对象是相对面向过程而言。
2)面向对象和面向过程都是一种思想。
3)面向过程强调的是功能行为。
4)面向对象是将功能封装进对象,强调具备功能的对象。
5)面向对象是基于面向过程的。
实例:将大象装进冰箱里面。
面向过程:把大象装进冰箱里。
(a)打开冰箱
(b)装入大象
(c)关闭冰箱
面向过程注重的是打开、存储与关闭的功能行为。
面向对象:
打开、存储与关闭均是冰箱这类事物对应的行为,因为操作的都是冰箱。因此可以将这些动作定义到冰箱当中,冰箱是一个实实在在存在的东西,称之为对象。而现在看到的不再是打开、存储与关闭,而是冰箱,冰箱中定义了打开、存储与关闭的动作。
图解:
总结:
1、面向过程是一种思想。C语言就是面向过程的语言。
2、面向对象的出现将复杂的事情简单化,面向过程需要面对多个动作,而现在只需要面对一个对象即可。
上图中左边需要从头到尾执行这些动作,而到了右边找到冰箱,让冰箱去打开、关闭和存储就可以了。角色由之前的执行者变成了指挥者(指挥对象做事情)。
面向过程是面向对象的基础,面向对象基于面向过程。
3、面向对象的思想落实到程序:
写程序时不是先定义功能,而是先面向对象,对象需要什么功能就就该功能定义到对象中去,封装好了之后下次若要使用该功能,则只要找到该对象,功能就有了。
开发时先找Java中是不是已经提供了相对性的对象,若有,则直接拿来使用;若没有,则再定义。
(找对象,建对象,用对象,并维护对象之间的关系)
在Java中,一切皆对象。
面向对象的三个特征:封装、继承和多态
二、类与对象的关系
类就是对现实生活中事物的描述,描述事物就是描述事物的属性和行为(属性对应类中的变量,行为对应类中的方法)。
对象就是这类事物实实在在存在的个体。
映射到Java中:
描述:就是class定义的类。
对象:就是对应Java在堆内存中通过new操作符产生的实体。(数据多了用对象存)
示例:对汽车进行描述
可以理解为类就是图纸,汽车就是堆内存中的实体。
package demo; //对汽车这类事物进行描述 class Car{ //描述颜色 String color = "red"; //描述轮胎数 int num = 4; //运行行为 void run(){ System.out.println("color = "+color+"\tnum = "+num); } } public class CarDemo{ public static void main(String[] args){ //生产汽车。在Java中通过new操作来完成 //其实就是在堆内存中产生了一个实体/对象。 Car c = new Car(); //将已有的颜色改为蓝色(指挥对象做事情) c.color = "blue"; c.run(); } }
内存中的体现:
对象的特点:封装数据,数据包括属性和行为(属性与行为统称为类中的成员,成员变量、成员函数)。
4000
操作对象:对象.对象成员
注意:
1)描述事物的类没有主函数,因为该类不需要独立运行,若想使用该类中封装的属性和功能,直接建立该类对象,随时都可以使用。
2)变量定义在了函数的外面,称之为成员变量。
成员变量与局部变量:
1)局部变量作用于函数或for循环中,并且存在于栈内存中,没有默认初始化值。
2)成员变量作用于整个类中,因为对象的存在而存在与堆内存中,有默认初始化值。(静态成员存在与方法区中)
匿名对象:
1、匿名对象是对象的简化形式。
2、匿名对象的两种使用情况。
1)对象的方法只调用一次。(若对一个对象进行多个成员调用,必须给该对象起名)
2)调用函数/功能时作为实际参数传递。
示例:
new Car().num = 5; new Car().color = "blue"; new Car().run();
第一句代码一执行完毕就变成垃圾,因为没有被使用。第二句话同样如此。
第三局代码有意义,因为调用的是方法,方法中有方法体,可以有运行内容在里面。
因此,匿名对象调用属性无意义,调用方法有意义,有时还可以简化代码。
三、封装
1、概念
封装,是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
2、封装的好处
1)将变化隔离。(属性如何变化和对象没关系)
2)便于使用。(不用了解内部构造)
3)提高重用性。
4)提高安全性。
函数是Java中最小的封装体。
3、关键字private
private:权限修饰符,用于修饰类中的成员(成员变量与成员方法)。私有后成员仅在本类中有效,外界无法直接访问。
对私有的成员变量一般都会提供相对性的两个访问方式set,get。(可以对外界输入的属性进行逻辑判断)
示例代码:
package demo; //对人进行描述 class Person{ //将age与name私有,不让外界直接访问 private int age; private String name; //描述speak功能 public void speak(){ System.out.println("name="+name+" age="+age); } //对外界提供age的设置与获取方式 public int getAge() { return age; } public void setAge(int age) { if(age<0){ System.out.println("输入错误"); return ; } this.age = age; } //对外界提供name的设置与获取方法 public String getName() { return name; } public void setName(String name) { this.name = name; } } public class PersonDemo{ public static void main(String[] args){ Person p = new Person(); //p.age = 20;报错,私有后无法访问 //对姓名和年龄进行设置 p.setAge(24); p.setName("zhangsan"); //调用p对象的speak功能 p.speak(); } }
输出结果为 :
注意:
1)封装不是私有,私有仅仅是封装的一种表现形式,不私有也能实现封装。(不同包中的默认权限也是一种封装形式)
2)私有是最小权限。
四、构造函数
1、特点
1)函数名与类名相同。
2)不用定义返回值类型。(与void不一样)
3)不可以写return语句。
2、作用
给对象进行初始化。
对象一建立就会调用与之相对应的构造函进行初始化。当一个类中没有构造函数时,系统会默认给该类加一个空参数的构造函数,方便该类进行初始化。
当类中自定义了构造函数后,默认的构造函数就消失了。此时若要建立该类对象,则必须访问指定的构造函数以进行初始化,否则会发生错误。
构造函数与一般函数的区别:
1)写法不同。构造函数名与类名相同。
2)运行上的不同。构造函数在对象一建立时就会运行,对对象进行初始化。一般方法是对象调用才执行,是给对象添加具备的功能。
3)同一个对象,构造函数只运行一次,而一般方法可以被该对象调用多次。
什么时候使用构造函数?
当分析事物时,该事物就具备了一些特性/行为,那么将这些内容定义在构造函数中。(如果构造函数中有未知内容参与运算,则定义参数)
注意:
构造函数可以被私有化(private),但此后无法在外部建立与之相对应的对象;若一个类中所有的构造函数都被私有化,则该类无法在外部建立对象,因为所有的对象都不能进行初始化动作。
3、构造代码块
1)作用:给所有对象进行初始化。(对象一建立就运行,而且优先于构造函数执行)
2)与构造函数的区别:
构造代码块是给所有对象进行统一初始化的,而构造函数是给对应的对象进行初始化的。
示例:
package demo; class Person{ private int age; private String name; //对象一初始化就具备name和age Person(String name,int age){ this.name = name; this.age = age; } //构造代码块,由于给所有对象进行初始化 { System.out.println("All-run"); } public void speak(){ System.out.println("name = "+name+"\tage = "+age); } } public class PersonDemo{ public static void main(String[] args){ //建立对象,并给构造函数传递指定参数 Person p1 = new Person("lisi",22); p1.speak(); Person p2 = new Person("wangwu",18); p2.speak(); } }
结果为:
五、this关键字
1、含义
this代表它所在函数所属对象的引用。即:哪个对象在调用this所在函数,this就代表哪个对象。
类里面的成员被使用完全也是由对象完成的。(省略了this.)
2、this的应用:
当定义类中的功能时,该函数内部要调用到该函数所属的对象时,用this来代替这个对象。但凡本类功能内部使用了本类对象,都用this来表示。
3、构造函数之间的调用
示例:
class Person{ private int age; private String name; Person(String name,int age 19f08 ){ //调用指定的构造函数 this(name); this.age = age; } Person(String name){ this.name = "张三"; } }
注意:
1)this语句只能用在构造函数的第一行。(初始化的动作要先执行,如果初始化中还有初始化,就先执行更细节的初始化)
2)一般函数是不能直接调用构造函数的,因为this语句只能用于构造函数间的相互调用,不能用于一般函数中。
六、static关键字
1、static(静态)
static:是一个修饰符,用于修饰类中的成员(包括成员变量、成员方法,不能修饰局部变量)。被static修饰后,成员变量就不在堆内存中了,而是被单独提取出来,存放在方法区中,每个对象都可以访问。(方法区中存放的是类中的方法以及类中的共享数据)
示例:
class Person{ private int age; private String name; //国籍相同,定义成静态成员,优化内存 static String country = "CN"; Person(String name,int age){ this.name = name; this.age = age; } } public class PersonDemo{ public static void main(String[] args){ Person p = new Person("xiaoqi",23); } }
1)被static修饰后的成员具备的特点:
(a)随着类的加载而加载。
当Person类被使用时,会被加载到内存中,而此时,静态成员country就已经存在了。Person类只要还在,静态成员就会一直存在于内存中,直至类在内存中消失。
(b)优先于对象存在。
Person类加载进内存中时,静态成员counrty就存在与内存中,而非静态成员name不存在,因为name只有在对象建立时才会存在于堆内存中。当对象建立并使用完毕后,name变不存在于堆内存中,而country依然存在。
(c)被所有对象所共享。
(d)可以直接被类名调用。(调用格式:类名.静态成员)
2)实例变量(对象变量/非静态变量)与类变量(静态变量)的区别
(a)存放位置
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
(b)生命周期
类变量的生命周期最长,随着类的消失而消失。
实例变量的随着对象的消失而消失。
3)静态使用时的注意事项
(a)静态方法只能访问静态成员。(非静态方法既可以访问非静态成员又可以访问静态成员)
(b)静态方法中不可以定义this,super关键字。(因为静态优先于对象存在,this,super代表的是对象)
(c)何时使用静态:
静态分静态方法和静态成员:
当对象中出现共享数据时,该数据被静态所修饰。但对象特有的数据要定义成非静态存放于堆内存中。
当功能内部没有访问到非静态数据(对象特有数据)时,可以将该功能定义成静态的。
4)静态的利弊
利:对对象的共享数据进行单独存储,节省内存;可以直接被类名调用。
弊:生命周期过长;出现访问局限性(静态虽好,却只能访问静态)。因此不建议定义过多的静态成员。
2、main函数
主函数是静态的。
public static void main(String[] args)
含义:
public 代表该函数的访问权限是最大的。
static 代表该函数随着类的加载就已经存在了。
void 代表主函数没有具体的返回值。
main 不是关键字,但是是一个特殊的单词,能被JVM识别。
String[] args 主函数的参数,参数类型是一个字符串数组。
主函数是固定格式的,能被JVM识别,唯一能改变的就是参数名args;JVM在调用主函数是,传入的是new String[0]。可以在启动JVM时给主函数传递一些参数,格式如下:
java MainDemo zhang lisi
java 启动虚拟机
MainDemo 需要执行的类
zhang lisi 给MainDemo的主函数传递的参数
3、生成帮助文档
当类中的成员都是静态成员时,该类就是一个工具类。为方便其他程序员使用该类中的功能,需要生成帮助文档,Java中提供了这样的工具:javadoc。(DOS命令行)操作格式如下:
javadoc -d c:\myhelp -author -version ArrayTool
javadoc 启动文档生成工具
-d c:\myhelp 文档存放目录为c:\myhelp
-author -version 文档中包括做作者和版本
注意:
1、要用javadoc工具生成文档时,该类要加public的权限修饰符。
2、需要生成帮助文档的成员前要用/** */在java源文件中注释好,而且其只提取被public修饰的成员前的注释文档。
3、文档注释中的特殊标识:
@author 作者
@version 版本
@param 参数
@return 返回值
示例:
/* 数组操作复习-----静态工具类 该工具类不需要建立对象 --- 构造函数私有化 方法都可以直接用类名调用(方法中均为访问到非静态数据) */ package day.day1; /** * 这是一个工具类,可用于对数据进行操作 * @author 陈滔 * @version v1.0 */ public class ArrayTool { private ArrayTool(){} /** * 在整数型有序数组中插入一个元素 * @param arr 接收一个int类型的数组 * @param key 需要插入的数 * @return 返回插入的位置 * */ public static int HalfSearch_1(int[] arr, int key) { int max = arr.length-1; int min = 0; int mid; while(min<=max){ mid = (max+min); if(key>arr[mid]) min = mid+1; else if(key<arr[mid]) max = mid-1; else return mid; } return min;//min = mid+1,若找的数不存在,其肯定在两个数之间 角标为mid+1 } /** * 查找整数型数组的指定元素 * @param arr 接收一个int类型的数组 * @param key 需要查找的数 * @return 返回该数的位置,不存在则返回 -1 * */ public static int HalfSearch(int[] arr, int key) { int max = arr.length-1; int min = 0; int mid = (max+min)/2; while(key!=arr[mid]){ if(key>arr[mid]) min = mid+1; else if(key<arr[mid]) max = mid-1; mid = (max+min)/2; if(min>max) return -1; } return mid; } /** * 获取整数型数组中的最大值 * @param arr 接收一个int类型的数组 * @return 返回最大值 * */ public static int getArrayMax(int[] arr) { int max = arr[0]; for(int x=0;x<arr.length;x++){ if(max<arr[x]) max = arr[x]; } return max; } /** * 对整型数组进行冒泡排序 * @param arr 接收一个int类型的数组 * */ public static void arrayBubbleSort(int[] arr) { for(int x=0;x<arr.length-1;x++){ for(int y=0;y<arr.length-1-x;y++){ if(arr[y]>arr[y+1]) swap(arr,y,y+1); } } } /** * 对整型数组进行选择排序 * @param arr 接收一个int类型的数组 * */ public static void arraySelectSort(int[] arr) { // TODO Auto-generated method stub for(int x=0;x<arr.length-1;x++){ for(int y=x+1;y<arr.length;y++){ if(arr[x]>arr[y]) swap(arr,x,y); } } } private static void swap(int[] arr, int x, int y) { int temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } /** * 对整型数组进行打印 * @param arr 接收一个int类型的数组 * */ public static void printArr(int[] arr) { System.out.print("["); for(int x=0;x<arr.length;x++){ if(x==arr.length-1) System.out.println(arr[x]+" ]"); else System.out.print(arr[x]+", "); } } }
4、静态代码块
1)格式:
static
{
执行语句;
}
2)静态代码块的特点
(a)随着类的加载而执行,只执行一次,并优先于构造函数执行。
(b)用于给类进行初始化。
一个类中可以有多个静态代码块和构造代码块。
5、对象的初始化过程
Person p = new Person("zhangsan",20);
这句话在内存中完成了以下8个动作:
1)因为new用到了Person.class,所以会先将Person.class加载到内存中。
2)执行类中的静态代码块,给Person.class进行初始化。(如果静态代码块存在)
3)在堆内存中开辟空间,分配内存地址值。
4)在堆内存中建立对象的特有数据,并进行默认初始化。(null,0)
5)对属性进行显示初始化。
6)对对象进行构造代码块初始化。
7)对对象进行与之对应的构造函数初始化。
8)将内存地址值赋给栈内存中的p变量。
6、对象调用成员过程。
Person类中所有方法都存在与方法区。
图例:
七、单例设计模式
设计模式:早期在建筑领域出现的概念,也就是总结得一些经验与方法,模式的出现让问题变得更简单。
Java中一共有23种设计模式,下面介绍单例设计模式。
单例设计模式:解决一个类在内存中只存在一个对象的方案。
步骤:
1)将构造函数私有化,禁止外部其他类建立对象。
2)在本类中创建一个本类对象。
3)提供一个公共方法以获取到本类对象。
单例设计模式有有两种实现方式:
1、饿汉式
对象一加载,方法区就存在就有s,堆内存中就有对象。
public class Single{ //将构造函数私有化 private Single(){} //在本类中创建本类对象 private static Single s = new Single(); //给外界提供一个公共的访问方式 public static Single getInstance(){ return s; } }
2、懒汉式
对象的延时加载。(类一加载s为空,且堆内存中还没有对象,只有调用方法的时候才建立对象。
public class Single { private static Single s = null; private Single(){} public static Single getInstance(){ if(s==null){ synchronized(Single.class){ /* * 多条语句操作共享数据,给这多条语句加上同一个锁,但是加上锁后效率变低 * 故再在外面加一层判断语句,以后就不会在判断锁了,提高了懒汉式的效率 */ if(s==null) s = new Single();//对象的演示加载 } } return s; } }
懒汉式的特点及存在的问题:
1)对象的延时加载。
2)延时加载在多线程访问时存在安全问题。
3)为解决多线程访问的安全的问题,加入同步synchronized,且其锁是该类对应的字节码文件对象。
4)加入同步之后会存在效率低的问题,因此加入双重判断语句。
饿汉式图解:
第二部分:面向对象的特点及其他
一、继承
1、继承的概述
继承是面向对象的第二个特征。当多个类中出现共性功能时,将功能向上进行抽取,定义在父类中,让子类继承父类。父类中的功能子类可以直接继承、使用。
注意:千万不要不要为了获取其他类的功能而继承,必须是类与类之间有关系。(用关键字extends申明两个类之间的关系)
package demo; //定义Person类 class Person { public void work() { System.out.println("work"); } } //定义Student继承Person class Student extends Person { } public class ExtendsDemo { public static void main(String[] args) { //父类Person中的方法,之类Student可以直接使用 new Student().work(); } }
2、继承的特点
1)提高了代码的复用性。
2)继承的出现让类与类之间产生了关系,有了这个关系才有了多态的特性。
Java语言中:只支持单继承,不支持多继承,因为多继承容易带来完全隐患。(即一个类中只要继承了一个类就不可以继承其他类)。但是Java保留了这种机制,并用另一种体现形式来表示,即多实现。同时,Java也支持多层继承。
如何使用一个继承体系中的功能呢?
想要使用体系,先查阅父类中的功能,因为父类中定义的是该体系中的共性内容,通过了解共性内容就可以知道该体系的基本功能。查阅到父类功能后,建立子类对象去使用这些功能。因为有可能父类不能创建对象(抽象类等),创建子类对象可以使用子类中的特有功能。(查阅父类功能,创建子类对象使用功能)
3、子父类中成员变量的特点。
(a)super关键字:代表父类对象的引用。super的使用与this的使用基本一致。(this关键字代表本类对象的引用)
(b)如果子父类中出现了非私有的同名变量时,子类要访问本类中的变量用this,子类要访问父类中的变量,用super。
4、函数覆盖(子父类中函数的特点)
当子类出现和父类一模一样的函数时,若子类要调用该函数,会运行子类对象的内容,如同父类的函数被覆盖一下。这就是函数的另一个特性,覆盖。(父类依然存在,只是没有运行)
当子类继承了父类,沿袭了父类的功能到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时没有必要定义新功能而是使用覆盖特性,保留覆盖的功能,并重写功能的内容。
示例代码:
/* * 子父类中构造函数的特点 */ class Phone{ public void show(){ System.out.println("show-number"); } } class NewPhone extends Phone{ //覆盖父类中的show方法 public void show(){ //在原来的功能上增加新的功能 super.show(); System.out.println("show-video"); } }
函数覆盖时注意事项:
1)子类覆盖父类,必须保证子类权限大于或等于父类权限,才可以覆盖,否则编译失败。
2)静态只能覆盖静态。
函数重载与覆盖的区别:
1)重载:只看函数的参数列表。
2)重写:子父类方法要一模一样(包括参数列表,返回值类型与函数名)。
以下两种情况不是覆盖:
父类:private void show()
子类:public void show() 子类不知道父类有该功能
父类:int show()
子类:void show() 编译错误,因返回值类型不同
5、子类的实例化过程(子父类构造函数的特点)
在子类对象进行初始化时,父类的构造函数也会运行,那是因为子类构造函数第一行有一条隐式语句super()会访问父类中空参数的构造函数,而且子类所有的构造函数默认第一行都是super()。
为何子类一定要访问父类中的构造函数?
因为父类中的数据子类可以直接获取,子类对象在建立时需要先查看父类是如何对这些数据进行初始化的,所以子类在进行初始化时会访问父类中构造函数,具体访问哪一个可以用super语句去指定。子类构造函数的第一行也可以手动指定this语句去访问本类中的构造函数,但必须要有一个构造函数访问父类中的构造函数。
示例代码:
class Animal { Animal(int num) { System.out.println("eat"); } } class Cat extends Animal { Cat(int num) { super(num);//访问父类中指定参数的构造函数 } }
6、final关键字
1)final可以修饰类、函数及变量。
2)被final修饰的类不可以被继承,以避免该类被继承,功能被复写后产生问题。(如,直接操作虚拟机的类)
3)被final修饰的方法不可以被复写。
4)被final修饰的变量是一个常量,只能赋值一次。
作为常量,书写时所有字母都大写,多个单词组成时中间加”_“连接。
全局常量:如 public static final double PI = 3.14;
5)内部类定义在局部位置上时,只能访问该局部被final修饰的成员。
7、抽象类
当多个类中出现相同功能,当功能主体不同,这时可以进行向上进行抽取,只抽取功能主体,不抽取功能定义。
抽象类的特点:
1)抽象方法一定定义在抽象类中。
2)抽象方法和抽象类必须被abstract修饰。
3)抽象类不可以new对象,因为抽象方法调用无意义。
4)抽象类中的方法要被调用,必须由子类复写所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。但抽象类中可以有非抽象方法。
抽象类与一般类的区别:
抽象类与一般类并无太大区别,该如何描述事物就如何描述事物,只不过该事物出现了一些看不懂的东西,这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体,故将其通过抽象方法表示。
抽象类比一般类多个个抽象方法,故抽象类不可以实例化。
8、Objdect类
Object是Java中所有类的父类(或超类),所有对象(包括数组)都继承这个类的方法。
常用方法:
boolean equals(Object obj) 判断两个对象是否相等,子类不复写则判断的是哈希值是否相等)
int hashCode() 返回对象的内存地址值,哈希值
String toString() 返回对象的字符串表示形式,getClass().getName()+"@"+Integer.toHexString(hashCode())
Class<?> getClass() 返回该类所对应的字节码文件对象
多线程中的常用方法(Object类中):
void wait() 当前线程等待
void notify() 唤醒线程池中的第一个线程
void notifyAll() 唤醒线程池中的所有线程
二、模板方法模式
模板方法模式就是在定义功能时,功能的一部分是确定的,另一部分是不确定的,但是确定的部分在使用不确定的部分,那么就将不确定的部分暴露出去,由子类复写来完成。(不确定的部分可以定义成抽象方法,确定的部分可以加final修饰)
示例代码:
package day.day1; /* 需求:定义一个类来计算程序运行的时间 思路: 1、通过System类来获取当前时间 2、将要运行的代码封装成一个函数,由于需要运行的代码不确定,故定义成抽象的 3、由于该类中定义了抽象方法,因此定义一个子类继承该类,并复写掉抽象方法 4、建立子类对象去实现该功能。 */ abstract class GetTime{ void runTime(){ //获取开始运行的时间 long start = System.currentTimeMillis(); runCode();//运行代码 //获取接收运行的时间 long end = System.currentTimeMillis(); System.out.println("程序运行"+(end-start)+"毫秒"); } //运行代码确定,定义成抽象的 abstract void runCode(); } class SubTime extends GetTime{ //子类复写掉父类中的抽象方法runCode(),将子类需要运行的代码定义在该函数中 void runCode(){ for(int x=0;x<1000;x++){ System.out.println(x); } } } public class AppTime { public static void main(String[] args){ //创建子类对象去完成计算程序运行时间的功能 new SubTime().runTime(); } }
结果为:
三、接口(interface)
1、定义
接口是一个特殊的抽象类,类中的方法都是抽象的,变量都是常量。Java中用关键字class来定义类,用interface来定义接口。
2、接口的格式
1)接口中常见定义:常量,抽象方法。
2)接口中成员修饰符都是固定的。(若忘记写了,系统会自动补齐)
成员常量:public static final
成员方法:public abstract
3、继承与实现的区别
类与类之间的关系:extends(父类有非抽象方法可以给子类使用)
类与接口之间的关系:implements(接口中的方法都是抽象方法,子类若想实现则需全部复写,接口也不可以直接创建对象。
接口与接口之间的关系:extends
4、多实现
1)接口可以被多实现,这也是java对多继承不支持的转换形式。
2)在Java中,一个类可以在继承一个类的同时实现多个接口。
3)接口与接口之间可以多继承。(因为都是抽象方法,没有方法体)
5、接口的特点:
1)接口是对外暴露的规则。
2)接口时程序功能的扩展。
3)接口降低了程序之间的耦合性。
四、多态
1、多态的基本体现
父类引用指向子类对象。(父类引用接收子类对象)
示例代码:
abstract class Animal { public abstract void eat(); } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } public void catchMouse() { System.out.println("猫抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("狗吃骨头"); } public void kanJia() { System.out.println("狗看家"); } } class DuoTaiDemo { public static void main(String[] args) { //父类引用指向子类对象--类型提升 Animal a1 = new Cat(); Animal a2 = new Dog(); } }
2、多态的好处
提高了程序的扩展性。
3、多态的前提
必须是类与类之间有关系,继承或实现。(通常还有一个前提,就是存在覆盖)
4、多态的弊端
只能使用父类引用访问父类成员。
如想访问子类中特有的方法,则应该进行类型转换,如:
Cat c = (Cat)a1;
c.catchMouse();
千万不要出现将父类对象转换成子类类型。如:
Animal a = new Animal();
Cat cat = (Cat)a;//报错,类型转换异常
新关键字:instanceof 判断某一类型的指向是否符合指定类型。
如:boolean flag = a instanceof Cat,判断a的引用是否指向Cat类型。
5、多态使用中的注意事项
1)在多态中,非静态成员函数的特点:编译看左边,运行看右边。
2)在多态中,成员变量的特点:无论编译和运行,都看左边。(针对重名的请况)
3)在多态中,静态成员函数的特点:无论编译运行,都看左边。
6、多态的应用
示例代码:
package day.day1; /* * 接口与多态的应用 * 接口降低了程序间的耦合性 */ interface PCI {//定义接口,对外暴露规则 public abstract void open(); public abstract void close(); } //定义主板 class MainBoard{ public void run(){ System.out.println("主板\trun"); } //使用多态的特性,完成程序功能的扩展,如PCI p = new NetCard(); public void usePCI(PCI p){ if(p!=null){ p.open(); p.close(); } } } //新进来的硬件只要实现接口,就能被主板所使用 class NetCard implements PCI{ public void open(){ System.out.println("网卡\topen"); } public void close(){ System.out.println("网卡\tclose"); } } class VoiceCard implements PCI{ public void open(){ System.out.println("声卡\topen"); } public void close(){ System.out.println("声卡\tclose"); } } public class MainBoardDemo{ public static void main(String[] args){ //新建一个主板对象 MainBoard mb = new MainBoard(); mb.run(); mb.usePCI(new NetCard());//使用网卡 mb.usePCI(new VoiceCard());//使用声卡 } }
运行结果:
图例:
五、内部类
将一个类定义在另一个类的里面,里面的那个类就称为内部类(内置类或嵌套类)。
示例代码:
class Outer { private static int x = 4; //内部类 class Inner { void show() { System.out.println("Inner.show"); } } //静态 内部类 static class StaticInner { static void function() { System.out.println("StaticInner:funchtion"); } public static void method() { System.out.println("StaticInner:method"); } } }
1、访问特点
1)内部类可以直接访问外部类中的成员,包括私有成员。(持有一个引用:外部内名.this)
2)外部类要访问内部类中的成员则必须建立内部类对象。
2、访问格式
1)当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,直接建立内部类对象。格式为:
外部类名.内部类名 变量名 = 外部类对象。内部类对象
Outer.Inner inner = new Outer().new Inner();
2)当内部类定义在外部类成员位置上时,可以被成员修饰符修饰,如:
private:将内部类在外部类中进行封装
static:内部类具备了静态的特性
3、内部类使用的注意事项
1)当内部类被static修饰时,只能访问外部类中被static修饰的成员
在外部其他类中,访问静态内部类中的非静态成员:new Outer.StaticInner().function();(通过内部类对象进行访问)
在外部其他类中,访问静态内部类中的静态成员:Outer.StaticInner.method();(都是静态的, 可以直接被类名调用)
2)当内部类中定义了静态成员,该内部类必须是静态的。
3)当外部类中的静态成员访问到内部类时,该内部类也必须是静态的。
4)当内部类在局部位置时,使用时要注意以下两点:
(a)不能被成员修饰符private,static等修饰。
(b)可以直接访问外部类中的成员,因为还只有外部类的引用(外部类名.this),但是只能访问它所在局部中被final修饰的局部变量。
何时使用内部类?
当描述事物时,事物的内部还有事物,内部事物就用内部类来描述。
4、匿名内部类
1)匿名内部类其实就是内部类的简写格式。
2)定义匿名内部类的前提:内部类必须是继承一个类或实现接口。
3)匿名内部类的格式:
new 父类名或接口名(构造函数的参数)
{
定义子类内容;(一般是复写父类中的方法)
}
4)其实内部类就是一个匿名子类对象,只是将定义类和建立对象封装成了一个整体。
5)匿名内部中定义的方法最好不要超过3个。
示例代码:
/* 需求:在没有父类和接口的情况下,如何通过匿名内部类运行其中的show方法。 分析:所有类的父类都是Object,因此可以通过Object来做。 */ class InnerDemo { public static void main(String[] args) { new Object() { public void show() { System.out.println("show--run"); } }.show(); } }
运行结果:
相关文章推荐
- Java基础知识之面向对象(3)
- java基础之面向对象-继承
- Java基础1:面向对象的三大特征
- Java基础之面向对象(小结)
- JAVA基础:JavaScript面向对象的支持(1)
- java基础:javascript面向对象的支持(1)
- java基础:javascript面向对象的支持(2)
- JAVA基础——面向对象,final,this,static,代码块
- Java基础---面向对象
- Java基础知识04-面向对象
- java基础学习面向对象之final关键字 五-9
- 黑马程序员——Java基础---面向对象(多态、异常、包)
- java基础面向对象与实例
- Java基础01 从HelloWorld到面向对象
- JAVA基础——面向对象
- Java中的基础----编程规则,开发原则,面向对象设计原则、面向对象的特征
- 黑马程序员--Java基础之面向对象(下)
- JAVA基础_Java面向对象三大特征
- Java-面向对象(基础编)--object类
- 黑马程序员-Java语言基础–面向对象 第10天