开发类的步骤:
1.找出类应该做的事,列出实例变量和方法
2.编写方法的伪码,思维导图
3.编写方法的测试程序 //可以对方法的某一部分进行测试
4.实现类,实现方法
5.修改bug
伪码是什么:伪码能帮助你专注于逻辑而不需要考虑到程序语法
包括三部分:实例变量的声明,方法的声明和方法的逻辑(逻辑最重要)用英文或中文来写
抽象类
不同的类,不断把共同特征向上抽取并组合到一起,组成一个类,这些类不应被初始化。
1.只定义,不能被实现,用abstract修饰
2.抽象方法在抽象类中,包含一个抽象方法的类就是抽象类,抽象类中可以没有抽象方法
3.抽象类不可实例化,子类只有重写了全部抽象方法,这个子类才能实例化
4.变量可重新定义和赋值
5.抽象类中可以有普通方法,抽象方法没有方法体
注:抽象类是有构造方法的
abstract class Person
{
public abstract String getDescription() //抽象方法不需要作用域
}
定义抽象方法的意义:
在实际开发过程中,抽象类中保存了许多共有的信息,将其方法定义为抽象方法的目的仅仅是为了声明作用,告诉子类要实现哪些功能,具体实现由子类决定。为什么抽象类中还有非抽象方法呢? 因为可能知道子类中一个具体业务是什么,所以就直接对其实现,子类可以继承后直接使用。
接口
类来自单亲家庭(extends),但可以扮演多重角色(implement)
接口(类的一组需求,这些类要遵从接口描述的统一格式进行定义):比如有一条狗和一只猪,,它俩都是动物所以要继承动物类,但是同时又是宠物,怎么能让它又实现宠物所拥有的方法呢? 可能会想到继承宠物类,但是Java不允许多重继承。为什么不允许多重继承呢,因为会产生“致命方块”类的问题,比如CD,DVD都继承自数字记录器,也都有i这个实例变量,而且它俩都用到了一个方法使用这个实例变量,当有一个类继承这两个类的时候,使用调用i的方法时,到底使用的是哪个类里的方法呢,这时没法确定。
从而引用了接口这个概念,它解决致命方块的方法很简单,把全部方法设为抽象的,这样一来子类就必须实现此方法,即使出现了和继承的同名方法,因为有接口,虚拟机就必须要实现接口的方法,因此java虚拟机在执行期间就不会搞不清楚用哪一个继承版本
接口是特殊抽象类,全部是抽象方法,不存在变量,因此接口没有构造方法,全局变量默认修饰public static final相当于常量,方法默认修饰public abstract(所以不可以加除了public的其它权限修饰符),因为全局变量是用static final修饰的,所以接口没有实例域。因此可以把接口看成是没有实例域并且全是抽象方法的抽象类
这时你又会想实现的两个接口有同样的方法怎么办。。正常人是不会这么做的
接口定义
public interface 接口名{
public abstract 返回值 方法名();
}
接口实现
public class Dog extends 类名 implements 接口名{ 先继承后实现接口
}
接口继承:一个接口可以继承多个接口
例:对象数组实现排序功能,必须实现comparable接口,重写compareTo方法,用Double包装类的compare进行比较,如果参数1大于参数2,返回正值
class Employee implements Comparable<Employee>{ //确保接口传入的是Employee对象
public int compareTo(Employee other){
return Double.compare(salary,other.salary);
}
}
对象克隆(很少使用)
当拷贝一个变量时,Person p1=new Person(), Person p1=p2 这时两个变量同时引用一个对象,改变一个变量所引用的对象,会对另一变量产生影响
Person p1=new Person()
Person p2=p1.clone(),
基本类型也如此
clone是一个Object里的protected(同类和子类使用)的方法,因此用户编写代码不能直接调用,Person类继承Object,所以它也是protcted的,所以只能在同类和其子类中使用此方法,连同包非子类都用不了,这样是违背我们的目的的,因此设计类的时候我们最好实现Cloneable接口,重写clone方法,把它访问权限变成public,让我们在其他类中也可以调用这个方法
既然clone是object里的方法那我们直接重写不就好了么?按道理是如此,但是设计者认为这个方法其实很少有人使用,所以虽然它是object的一个方法,但是不能直接重写,而是继承一下接口标示一下,告诉虚拟机我们要重写clone方法了,这个接口里什么也没有仅仅是标示的作用。
这个实现的是浅拷贝,假如拷贝的对象之中,某个属性包含一个引用,要实现对这个引用也进行拷贝,则需要深拷贝
例: class Employee implements Cloneable{
public Employee clone()
{
Employee cloned=(Employee)super.clone();调用父类的克隆方法,将本对象进行克隆
cloned.hireDay=(Date)hireDay.clone();
return cloned;
}
}
内部类:has-a
作用 :
1.内部类方法可以访问该类定义所在的作用域中(外部类)的数据,包括私有数据
2.内部类可以对同包中其它类隐藏,便于实现功能
3.可以实现多继承,内部类和外部类都可以继承一个类(最有用)
4.解决命名冲突(解决了接口和继承方法名相同不知道调用是谁的方法的问题,谁近就调哪个)
内部类中总有一个隐式引用,指向创建它的外部类对象
1.成员内部类:可以访问外部类成员属性和方法(包括私有),当成员内部类和外部类有同名属性或方法时,默认访问内部类成员,若访问外部类:
外部类.this.成员变量 外部类.this.成员方法
外部类若想访问内部类方法属性,必须先创建对象,再调用其方法
一般外部类有个成员方法创建内部类对象(这样其他类只要创建外部类对象调用其方法就可以访问内部类)
若其它类想创建内部类对象,则必须先创建外部类对象
Outer outter=new Outer();
Outer.Inner inner=outter.new Inner()
2.局部内部类:定义在外部类一个方法内,对外界隐藏,外部类其它方法也不能访问(不能访问局部变量!!)
局部内部类,定义在一个方法中,并在方法中创建对象,其它类访问内部类的时候,需要调用外部类的方法,然而方法执行后,局部变量立即消失,而内部类对象不是立即消失,就会导致内部类对象操作的局部变量不存在了,也就是两者的生命周期不同
在局部内部类,如果内部类调用方法中的局部变量,局部变量要加上final
1.为什么不加final程序会报错?
当创建内部类对象的时候,使用局部变量,由于局部内部类定义在方法当中,调完方法之后里面局部变量就会被销毁,但是这个时候内部类的对象有可能还存在(只要一直引用它),所以导致了局部变量与对象的生命周期不同,导致了错误。
2.如何解决
使用final关键字,使用final关键字之后相当于把局部变量偷偷的复制了一份到对象当中去,保证了局部变量和对象的生命周期统一
3.匿名内部类(重点):所谓的匿名内部类其实是匿名子类对象,只是该对象没有名字而已
当想要定义一个回调函数(递归),使用匿名内部类比较方便
1.只创建一个实例 new SuperType(参数){方法}
ta.test(new product(){ //当类的参数是一个接口或抽象类时使用匿名内部类
public double getPrice(){ //匿名内部类是product的子类
return 567;}
})
匿名内部类访问的局部变量要用final修饰
4.静态内部类(了解) 相当外部类
Inner in=new Outter.Inner()
编译的时候编译器把它编译成外部类$内部类.class,虚拟机对此一无所知
如果内部类中包含有静态成员,那么java规定内部类必须声明为静的静态内部类
如何判断是设计类、子类、抽象类或接口呢?
1.新的类无法对其它的类通过IS-A测试,就设计为新的类
2.只有在需要某个类的特殊化版本时,以覆盖或增加新的方法来继承现有的类
3.当你需要定义一群子类的模板,又不想让程序初始化模板,就设计为抽象类
4.如果想定义类扮演某个角色,使用接口
网友评论