------- android培训、java培训、期待与您交流! ----------
李小龙__光是知道是不够的,必须加以运用;光是希望是不够的,非去做不可. 学习java就像练武术,不用是会荒废的.
<1> 面向对象之继承
类与类之间的关系 1依赖 2.聚合 3.继承 上个帖子的继承,这个帖子专门来讲.
继承的由来
将多个类中公共的内容向上抽取产生了父类(基类 超类)
这个被抽取的类叫子类
通过这种方式我们可以节省代码
继承的格式
class子类 extends 父类似{
}
********************************
通过继承,子类自动拥有父类的所有非private成员。
也可以说private成员子类可以继承,但是不能使用。因为private限定使用的范围。
********************************
继承的好处
继承的出现提高了代码的复用性。
继承的出现让类与类之间产生了关系,提供了多态的前提。
Java的继承规则
单继承
java中只支持单继承,一个父类可以派生多个子类.
为什么只支持单继承?就是为了避免混淆
classFather{
void fun(){}
voidmethod(){}
}
classAFather{
voidfun(){}
}
classASon extends Father,AFather{
//当前ASon有两个父类 Father ,AFather,那么对于ASon子类来说
它里面存在fun方法,这个方法是从哪一个父类继承?为了避免这种
情况的存在,java中只允许单继承
}
classBSon extends Father{
}
说难听点就是一个儿子只能有一个爹,一个爹可以有多个儿子,呵呵,明白就好,别外传.
多重继承
java中支持多重继承
classGradeFather{
voidfun(){}
}
classFather extends GradeFather{
voidfun(){} //这个方法是从GradeFather中继承的
}
classSon extends Father{
//当前Son这个类也可以看成是GradeFather的间接子类.
voidfun(){} 这个方法是从Father继承的。
}
通过多重继承产生了一个继承的体系,怎样使用体系
上层的类中定义的行为对于这个体系来说,所有下层的类中都包含.
对我们来说在学习一个体系时,从上层来观察.通过上层能了解整个体系的基本行为.
真正使用时,使用的最下层的类。
上层:标识的是整个体系的功能
下层:标识的是特性的功能(根据具体的要求来选择)
如何使用继承
记住一句话: 不要为了继承而继承(不要为了使用某个属性或方法去特意的继承)
我们什么时候使用继承,要进行具体的分析,继承其时是一种is关系
举例:
class动物{
}
class哺乳动物{
voideat();
}
class犬科 extends 哺乳动物{
}
class猫科 extends 哺乳动物{
}
class狗 extends 犬科{}
class狼 extends 犬科{}
class猫 extends 猫科{}
class虎 extends 猫科{}
class蝙蝠 extends 哺乳动物{}
class跳蚤{
//如果它也有一个吃的行为,就不应该继承犬科,猫科,也不能继承哺乳动物。
}
继承中的构造方法
首先:构造方法不能被继承
通过下面代码发现,当子类对象实例化时Son son=new Son(),父类构造先执行了,然后执行的是子类构造.
//父类
classFather
{
Stringname;
Father(Stringname){
super();//执行Object父类的无参构造方法
System.out.println("father构造");
}
Father(intage){
}
Father(){}
}
//子类
classSon extends Father
{
Stringsex;
Son(){
//super(); //执行Father父类的无参构造方法
super("tom");//执行Father父类的字符串参数的构造方法
System.out.println("son构造");
}
}
为什么出现这种情况?
因为所有的构造方法中默认执行的第一句话都是super();
super();它代表的意思是执行父类的无参构造方法。
java中的所有类都有一个默认的父类 Object类,它是所有java类的父类.
父类的构造方法执行,做了什么事情?
父类的构造方法执行的目的是为了帮助子类对象实例化.
代码分析:是因为每一个构造方法中有super()
原理分析:父类构造方法被执行是帮助子类对象实例化
super()默认存在于每一个构造方法的第一句,写与不写一样
如果父类中不存在无参构造,那么必须在子类中指定通过哪一个构造方法去实例化对象
super(参数);
在构造方法中的super()与this()
super()它的作用:执行父类的构造方法
this() 它的作用:执行本类的构造方法
super()与this()在使用时注意事项
1.它们只能出现在构造方法中
2.它们如果要出现,必须是构造方法中的第一句.
3.super()与this()不能共存.
为什么中只能出现一次,并且出现在第一行,因为如果要出现了多次,就会执行多次构造方法.
继承中的成员属性
如果子类中存在与父类中重名的成员属性
在子类中有一个方法,它显示这个重名的属性
this存在成员方法中作用:用来区*部与成员属性
super存在成员方法中作用:用来区分子类与父类中重名的成员
classFather
{
Stringname="tom";//父类成员变量
}
classSon extends Father
{
Stringname="james"; //子类成员变量
publicvoid show(){
Stringname="tony"; //局部变量
System.out.println(name); //局部变量name
System.out.println(this.name);//本类中的name 属性
//要得到被子类隐藏的父类中的name属性
System.out.println(super.name);//通过super可以得到父类中的name属性
}
}
继承中的成员方法
重写:子类中存在一个与父类中一样的方法
一样的意思是返回值类型,方法名,参数列表都一样。
重写的作用:通过重写可以将父类中的方法进行功能扩展.
重写的注意事项:
1.静态只能覆盖静态
2.重写的方法的权限修饰符要大于等于被重写的方法
3.私有的方法不能被重写.
关于多态的两种表现形式:重写与重载
重写与重载的区别?
重载:一个类中具有相同的方法名,参数的类型,个数,排列顺序不同产生了重载.
重写:子类中有一个与父类一样的方法,方法的返回值类型,方法名,参数列表一样。
重写的作用:可以在子类中对父类的方法进行功能扩展.
在重写的方法内如果要使用父类中的方法可以使用super调用。
final使用
final是一个修饰符
修饰类: 代表这个类不能被继承
String类就是一个final类
修饰方法: 代表这个方法不能被重写
**修饰属性:代表这个属性是一个常量 在定义时,一般属性名都要大写。final double PI=3.14;
在实际操作中什么时候使用final修饰属性
例如在开发中求圆的面积会使用圆周率,它的值就应该是3.14,而不能改变。
这个时候这个变量就应该是final的。
我们做的扑克牌程序,它的花色与值也是不能改变的,也应该是final的。
小练习:
classFinalDemo{
finalint i; //如果 final int i=1;这种情况也会出问题,构造不能再赋值
FinalDemo(inti){
this.i=i;
}
publicstatic void main(String[] args){
FinalDemofd=new FinalDemo(10);
//fd.i=100;//也会出问题.原因:构造方法中赋值了,不能再改变.
System.out.println(fd.i);
}
}
如果当前i没有初值,那么我们可以在构造方法中对其进行一次赋值操作。
当对象产生后就不能在对其进行赋值操作。
构造代码块与局部代码块
什么叫代码块 { } 一对大括号中的内容叫代码块
什么叫构造代码块代码块声明在类的成员位置上叫构造代码块
什么局部代码块 代码块声明在方法内
构造代码块的作用: 它优先与构造方法执行,在构造代码块中的内容是所有的构造方法都要执行的内容。
局部代码块的作用:限定局部变量的生命周期
static关键字
它随着类的加载而加载,优先于对象产生。放在方法区的静态区内。static修饰的成员,可以通过类名去调用。
static是一个修饰符
修饰属性 叫类属性 静态属性
特点:1.在内存中只有一个,所有的对象共享。
2.它存在于内存的方法区的静态区域内,它是随着类的加载而加载的。它的生命周期
与类的类的生命周期一样。
3.对于静态(类)属性 我们在使用时一般不使用引用(对象)调用,而是使用 类名.静态属性。
什么时候使用static属性?
static修饰的属性在内存中只有一个,比较节省资源.
这个数据所有的对象的值都一样。
当前这个属性是用来描述的类的相关信息,这个属性也应该是static.
静态属性与实例属性的区别
1.内存空间 静态属性在方法区的静态区域内 实例属性在堆内
2.生命周期 静态属性是随着类的加载而加载,它与类的生命周期一样
实例属性它是属于对象的与对象的生命周期一样。
3.共享: 静态属性在内存中只有一个,所有对象使用的是同一个。
实例属性属于每个对象,每个对象有自己的实例属性
4.调用: 静态属性可以使用 引用(对象).静态属性 也可以使用 类名.静态属性 在实际操作中类名调用使用比较多。
实例属性 引用(对象).实例属性
修饰方法
static修饰的方法 类方法 静态方法
static方法也是随着类的加载而加载
调用时也可以通过类名.类方法 引用(对象).类方法名
注意事项:
1.在static方法内只能使用static成员。报错:Demo4.java:17: 错误: 无法从静态上下文中引用非静态
2.在static方法内不能使用this,super这样的关键字
原因:this指代某个对象,对于static方法它是随着类的加载而加载的。
这个时候对象还没产生,所以不能使用this
在非静态方法内使用静态成员是可以的。
静态方法什么时候使用?
如果当前方法内所使用的属性不是成员属性,这时这个方法应该是static。
当前类是一个工具类,其中的方法完成的是一个独立的功能.
三种方法 类方法 实例方法 构造方法各自的特点
1.结构: 类方法 使用static修饰的 可以有返回值 如果没有使用void
实例方法 使用非static修饰的 可以有返回值 如果没有使用void
构造方法 它没有修饰符(权限除外) 没返回值 void也没有
2.应用: 类方法 它一般描述的是与成员属性无关的操作。
实例方法 它描述的是与成员属性有关的操作。
构造方法 它是用来创建对象。
3.调用: 类方法 可以使用类名调用也可以使用引用(对象)调用
实例方法 只能使用引用(对象)调用
构造方法 想要执行,创建对象。
4.内存空间:
类方法:方法区的静态区域内
实例方法构造方法都是在方法区。
主方法也是static(了解)
publicstatic void main(String[] args){ }
public 权限修饰符
static 静态方法 主方法在被jvm调用时直接通过类名调用,不需要对象
void jvm不需要主方法的返回值。
main 固定
String[]args 参数 命令行参数 学习中做测试
主方法是由jvm调用,我们可不可以调用哪?
主方法是一个静态的方法,可以通过类名去调用。
类的组成
class类名{
成员属性 :类属性(static修饰的) 实例属性.(非static修饰的)
在一些java书中所说的成员属性一般指的都是实例属性。
成员方法:类方法(static修饰) 实例方法(非static修饰)
构造方法
}
静态代码块
static{} 声明在类中。
优先于构造代码块,构造方法执行,并且只执行一次。
静态代码块中定义什么内容?静态代码块什么时候使用?
静态代码块中所使用的成员也必须是静态的。
对于静态代码块它是用来描述类的相关信息。并且只执行一次的内容。
对于比较消耗资源,然后加载一次就可以使用内容。放到静态代码块中。
对于程序在启动时需要优先加载的内容,也可以放入到静态代码块中。
javadoc命令使用
/**
文档注释 java特有的。
*/
我们可以通过javadoc.exe命令将我们程序中的文档注释抽取出来形成 xxx.html文件
javadoc-d c:\a
-dc:\a 作用是将从程序中的文档抽取的文件放入到指定的目录(c:\a)下。
@param 生成参数
@return生成返回值
@author 生成作者
@version生成版本
javadoc-d 目录 源文件.java -author –version (要生成作者与版本格式)
举例: 打开cmd javadoc -d d:\a Demo.java-author –version 将Demo.java 文件中的文档注释抽取出来放入D盘的a文件夹下形成html文件
单实例
使用模式的好处:可以让我们代码更健壮,安全,结构更严禁。
单实例设计模式:它解决的问题是保证对象唯一化.
怎样能保证在堆内存中只有一个SingleTon对象,所有人使用的是同一个?
分析:
1.不能让外部任意new出来SingleTon对象.
2.对外提供公共静态的方法可以获得本类对象.
为什么?因为如果是实例方法需要对象调用
3.在本类中声明一个私有的静态本类对象
代码实现步骤:
1.将构造方法私有化 private 构造
2.创建公共static方法返回本类对象 public static SingleTon getInstance(){returns;}
3.在本类中创建一个本类的静态对象 private static SingleTons=new SingleTon();
单实例模式在实际开发中什么时候使用?
例如在开发中我们要连接数据库,对于java连接外部设备时是比较消耗资源的。
为了节省资源,我们就可以使用单实例模式得到一个连接数据库的对象。
所有人要想操作时,都使用同一个对象。
例如DataSource对象它的获得就是一个单实例
//单实例---饿汉式(非延迟加载)
classSingleTon
{
//3.在本类中定义一个本类的对象
privatestatic SingleTon s=new SingleTon();
//1.私有化构造
privateSingleTon(){}
//2.提供公共的静态方法可以获得本类对象
/*
参数:不需要
返回值:返回值类型是SingleTon
*/
publicstatic SingleTon getInstance(){
returns;
}
}
//单实例---懒汉式(延迟加载) 有线程安全问题 写线程日志时在提供解决方法
classSingleTon
{
//3.在本类中定义一个本类的对象
privatestatic SingleTon s;
//1.私有化构造
privateSingleTon(){}
//2.提供公共的静态方法可以获得本类对象
/*
参数:不需要
返回值:返回值类型是SingleTon
*/
publicstatic SingleTon getInstance(){
if(s==null){
s=newSingleTon();
}
returns;
}
}
今日帖子练习:
ATM操作
程序运行时
提供功能"请选择操作 1.存钱 2.取钱 3.查看 4.退出 5.注册 6.登录
分析:
实体 人 ATM
ATM行为:存 取 查看 退出注册 登录
人:属性 money
对于我们当前程序来说,ATM的几个操作无非就是对人的money属性进行操作。
ATM类要与Person类之间要存在关系。
代码实现:
import java.util.*; // 导入包
class Test6 {
publicstatic void main(String[] args) {
Scannersc=new Scanner(System.in);
//创建一个ATM对象
ATMatm=new ATM();
while(true){
System.out.println("请选择操作 1.存钱 2.取钱 3.查看 4.退出 5.注册 6.登录");
inttype=sc.nextInt();//接收键盘输入的信息
switch(type){
case1:atm.save();break;
case2:atm.get();break;
case3:atm.search();break;
case4:atm.exit();break;
case5:atm.reg();break;
case6:atm.login();break;
default:System.out.println("无此操作");
}
}
}
}
//定义ATM类
class ATM{
Personp; //做为ATM的一个属性存在。
Scannersc=new Scanner(System.in);
//存钱
voidsave(){
if(p==null){
System.out.println("请先注册");
return;
}
if(p.flag){
System.out.println("请输入要存入的金额");
intmoney=sc.nextInt();
p.money+=money;
System.out.println("存款成功");
}else{
System.out.println("请先登录");
}
}
//取
voidget(){
if(p==null){
System.out.println("请先注册");
return;
}
if(p.flag){
System.out.println("请输入要取款的金额");
intmoney=sc.nextInt();
//判断余额是否充足
if(money>p.money){
System.out.println("余额不足");
return;
}
p.money-=money;
System.out.println("取款成功");
}else{
System.out.println("请先登录");
}
}
//查
voidsearch(){
if(p==null){
System.out.println("请先注册");
return;
}
if(p.flag){
System.out.println("帐号:"+p.id+" 密码:"+p.password+" 银行余额:"+p.money);
}else{
System.out.println("请先登录");
}
}
//退出
voidexit(){
System.exit(0);//让jvm停止
}
//注册对人的id 与password进行赋值
voidreg(){
if(p==null){
p=newPerson();
System.out.println("请输入要注册的帐号");
p.id=sc.nextInt();
System.out.println("请输入要注册的密码");
p.password=sc.nextInt();
System.out.println("注册成功");
}else{
System.out.println("已经注册");
}
}
//登录的行为
voidlogin(){
//判断是否注册
if(p==null){
System.out.println("请先注册");
return;
}
System.out.println("请输入帐号");
intid=sc.nextInt();
System.out.println("请输入密码");
intpassword=sc.nextInt();
if(checkPerson(id,password)){
//让这个人是登录状态
p.flag=true;
System.out.println("登录成功");
}else{
System.out.println("帐号或密码错误");
}
}
/*
功能:判断帐号与密码是否正确,如果正确返回true,否则返回false
参数: 帐号 密码
返回值:正确返回true,否则返回false
*/
privateboolean checkPerson(int id,int password){
returnp.id==id && p.password==password;
}
}
//定义人类
class Person{
intmoney;
intid;//帐号
intpassword;//密码
booleanflag;//它代表人是否登录 true登录 false未登录
}