-------android培训、java培训、期待与您交流! ----------
一 封装 :是指使用 private,protectecl,public和默认权限这几种 修饰符关键字,修饰实现隐藏对象的属性和实现细节,然后在使用public权限对外提供公共
的访问方式:set和get;
set:是用于赋值,在set方法中可以加入逻辑判断的语句对访问的数据进行操作提高代码的健壮性,get用于取值;
如示例:
/*
* 定义一个使用private修饰的int值age
*对外提get和set方法在set赋值方法中使用逻辑判断如果传进来的值大于120或
*小于0就是不能把该值赋给age。而自己给他一个默认值25;这样就提高了代码的安全性,隐藏了内部的细节提高访问的方法给调用者;
*/
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<120 && age>0){
this.age = age;
}else{
this.age=25;
}
}
(1):好处:将变化隔离,便于使用,提高重用性,提高安全性;
(2):封装的原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供方法对其访问;
二 继承
(一)继承的格式:修饰符 SubClass extends SuperClass { 代码块}
(二)继承概述:
(1):继承(Inheritance)通过extends关键字来实现,其中SubClass称为子类,SuperClass称为父类或基类 超类。如果使用public修饰符那么
该类在整个项目中可见;不写public修饰符则该类只能在当前包可见;不可以使用private和protected修饰符;
(2)在java中只支持单继承,即每个类只能有一个直接父类,继承表达式是 is a 的关系,或者说是一种特殊和一般的关系;
例如:学生继承人 或苹果继承水果 等等。
(3) java中为什么只支持当继承,不支持多继承:
因为多继承容易带来安全隐患:当多个父类中定义了相同功能,但其各自的功能内容不同时,子类对象不确定要运行哪一个;
但是java保留这种机制,并用另一种体现形式来完成表示:即多实现------接口;
(4) 在java中所有java类都直接或间接的继承了java.lang.Object类。Object类是所有Java类的祖先。在定义一个类是,没有使用extends关键字,那么
这个类直接继承Object类。
例如:public class MyObject{ }这段代码表明:MyObject类的直接父类为Object。
(5)在java中支持多层继承,也就是一个多层的继承体系;
想要使用这个体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能;可以通过了解共性功能,就可以知道该体系的基本功能;
那么在具体调用时,要创建最子类的对象,为什么呢?
原因一:因为有可能父类不能创建对象,因为他是抽象类;
原因二:是创建子类对象可以使用更多的功能,包括基本的也包括特有的即父类的;
继承的特点:
(1):提高了代码的复用性;
(2):让类与类之间产生了关系,有了这个关系,才有了多态的特性;
注意:
(1)不要为了获取其他类的功能,简化代码而继承;继承必须是类与类之间有所属关系才可以继承,所属关系就是 is a;
(2)继承public和protected修饰的属性和方法,不管子类和父类是否在同一个包里子类都可以使用父类的非私有属性和方法;
(3)继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里;
(4)无法继承private修饰的属性和方法;
(5)无法继承父类的构造方法;
(三):继承的使用:
(一)类中成员的特点:
(1)变量:
如果子类出现非私有的同名成员变量时,子类要访问本类中的变量,用this,子类要访问父类中的同名变量要用super;
this代表本类对象的引用;
super代表父类的引用且super必须出现在子类中(子类的方法和构造方法中),而不是其他位置,super可以访问父类的
属性,方法和构造方法,但不能访问父类的private成员;
(2)子父类中的函数:
当子类中出现和父类一模一样的函数时,当子类对象调用该函数会运行子类函数的内容这就如同父类函数被覆盖一样;
这就是函数的另一个特性:重写(覆盖)
覆盖就是在子类中可以根据需求对父类继承的方法进行重新编写称为方法的重写或方法的覆盖(overriding);
注意:方法的重写必须满足如下要求
1:重写方法和被重写方法必须具有相同的方法名;
2:重写方法和被重写方法必须具有相同的参数列表;
3:重写方法的返回值类型必须和被重写的方法的返回值类型相同或是其子类;
4: 重写方法不能缩小被重写方法的访问权限。
(3)重载和重写的区别和联系?
1:重载涉及同一个类中的同名方法,要求方法名相同,参数列表不同,与返回值类型无关;
2:重写涉及的是子类和父类之间的同名方法,要求方法名相同,参数列表相同,返回值类型相同(或是其子类);
如示例:
public static void main(String[] args) {
// TODO Auto-generated method stub
Zi z=new Zi();
z.show();
}
}
/*
* 创建父类 Fu ,在父类中有变量name并赋值为李四;
* 通过show方法打印name的值
*/
class Fu{
String name="李四";
void show(){
System.out.println(name);
}
}
/*
* Zi类通过extends关键字继承父类并拥有父类的非私有属性和函数;
* 并重写父类的show方法,子类要使用父类的show方法要使用super关键字;如果不使用super关键字来显示的调用的话系统默认为this调用这样就会
* 出现递归就是子类一直在调用子类的show方法,也就是死循环会造成内存溢出;
* 字类要使用父类的同名属性通过this关键字将子类的引用指向父类来调用
*
*/
class Zi extends Fu{
void show(){
super.show();
this.name="张三";
System.out.println(this.name);
super.show();
}
}
(4)继承条件下构造方法的调用规则如下:
1: 如果子类的构造方法中没有通过super显示调用父类的有参构造方法,也没有通过this显示的调用自身的其他构造方法,则系统会默认
先调用父类的无参构造方法,在这种情况下,写不写“super();”语句效果都是一样。
2:如果子类的构造方法中通过super显示调用父类的有参构造方法,那将执行父类相应的构造方法,而不执行父类的无参构造方法!
3:如果子类的构造方法中通过this显示调用自身的其他构造方法,在相应构造方法中应用以上两条规则;
4:注意:如果存在多级继承关系,在创建一个子类对象是,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造
方法为止。
5:为什么子类一定要访问父类中的构造函数:
因为父类中的数据子类可以直接获得,所以子类对象在建立时需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始
化时 要先访问一下父类中的构造函数;如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定;
但是:super语句一定要定义在子类的构造函数的第一行。
(二):final关键字
(1)final可以修饰类,方法,变量:
可以修饰成员变量,也可以修饰局部变量;当在描述事物时,一些数据出现的值是固定,那么这时为了增强阅读
性都给这姓值起个名字方便阅读,而这个值不需要改变,所以加上final修饰,作为常量,常量的书写规范所有字
母都是大写,如果有多个字母组成单词间通过“_”链接;
(2)final修饰的类不可以被继承;
例如:在java中提供了很多类就是final类,比如String类 Math类等他们不能再有子类。
(3)final修饰的方法不可以被覆盖;
例如:Object类中的一些方法:如getClass() , notify(),wait()等都是final方法,只能被子类继承而不能被重写,
但是hashCode(),toString,equals(Object obj )不是final方法,可以被重写。
(4)final修饰的变量是一个常量,只能被赋值一次;
使用final修饰的引用变量,变量的值是固定不变的,而变量所指向的对象的属性值是可变的;
(5)内部类定义在类中的局部位置上时,只能访问该局部被final修饰局部变量。
(三):抽象类:
(1) 抽象类概述:当多个类中出现相同功能,但是功能主题不同,这是可以进行向上抽取的,这时就可以定义抽象类为父类;
(2)抽象类的特点:
(1):抽象类和抽象方法都是通过abstract关键字修饰;
(2):抽象类不能被实例化,抽象类中可以没有或可以有一个甚至多个抽象方法,也可以全部是抽象方法;
(3):抽象方法只能写在抽象类中,抽象方法没有方法实现,子类必须重写所有的抽象方法才能实例化,否则字类还是抽象类;
(3):抽象类和一般类的区别:
1: 抽象类和一般类没有太大的区别,抽象类中只不过是多了个修饰符abstract,这是用于在抽象类中描述一些不确定的部分,也是该事
物的需要明确出来,但是无法定义主体所以通过抽象方法来表示;
2:抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法,
3:抽象类不可以实例化,
4:抽象类中的特殊之处是:抽象类中可以不定义抽象方法,这样就是为了不让该类实例化,但这样的类有一般不多见;
(四)模板模式:
什么是模板模式?
模板模式就是在定义功能时,功能的一部分时确定的,但是有一部分时不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定部分
暴露出去由子类来完成;例如在现实生活中的模子一样样式是确定而要用什么材料不知道,你只要把材料放进去我就给你做出你想要的结果;
public static void main(String[] args) {
// TODO Auto-generated method stub
SubTime s=new SubTime();
s.getTime();
}
}
//定义模板
abstract class GetTime{
//已知的内容且不需要改变的所以使用final修饰;
public final void getTime(){
//调用window的方法获取当前时间的毫秒时间
long staart=System.currentTimeMillis();
//调用子类实现未知的方法体;
rencode();
//获取程序运行后的当前时间的毫秒时间
long end=System.currentTimeMillis();
//两个时间相减得到运行时间
System.out.println("程序运行的时间是:"+(end-staart)+"毫秒");
}
//把为未知的内容定义成抽象方法
public abstract void rencode();
}
//子类继承父类
class SubTime extends GetTime{
//实现父类的抽象方法
@Override
public void rencode() {
// TODO Auto-generated method stub
for (int i = 0; i <500; i++) {
System.out.println(i);
}
}
}
(五)接口:接口就如同一种约定,表示一种能力,体现了约定和实现相分离的原则:
格式: 修饰符 interface 接口名 {代码主体}
(1)接口和类,抽象类是一个层次的概念,命名规则相同。如果修饰符是public,则该接口在整个项目中可见,如果省略修饰符则该接口只能在当前保可见;
(2)接口中可以定义常量,不能定义变量;接口中属性都会自动用publicstaticfinal修饰,即接口中属性都是全局静态常量,接口中的常量必须在定义是指定
初始值;例如:
public static final int PI=3.14;
int PI=3.14; 这两种定义语句的效果是一样的,但是 int PI;这样定义是错误的,因为在接口中的变量都是静态的常量要有初始值;
(3)接口中所有方法都是抽象方法,接口中方法都会自动用public abstract修饰,即接口中只有全局抽象方法;
(4)接口和抽象类一样是不可以实例化的,接口中也不能有构造方法;
(5)接口之间可以通过extends实现继承关系,一个接口可以继承多个接口,但接口不能继承类,
(6)一个类只能有一个直接父类,但可以通过implements实现多个接口。类必须实现接口中的所有方法,否则必须定义为抽象类,类在继承父类的同
时又实现了多个接口时,extends必须位于implements之前。
示例:
public static void main(String[] args) {
// TODO Auto-generated method stub
//实现类对象调用show方法
Student s=new Student();
s.show();
//接口引用指向实现类对象调用show方法
Iners ss= new Student();
ss.show();
}
}
//定义接口
interface Iners{
//定义常量
public static final int number=5;
//定义抽象方法
public abstract void show();
}
interface Inerts{
//定义常量
public static final int number=8;
//定义抽象方法
public abstract void show();
}
class Preson{
String name;
}
//Student继承Preson类在实现两个接口,也可以实现多个接口
class Student extends Preson implements Iners,Inerts{
//实现接口中的抽象方法;
@Override
public void show() {
// TODO Auto-generated method stub
this.name="张三";
System.out.println(name);
}
}
小结:
面向接口编程可以试想接口和实现的分离,这样做的最大好处就是能够在客户端未知的情况下修改实现代码,那么什么时候应该抽象接口呢?
一种是用在层和层之间的调用,层和层之间最忌讳耦合度过高或是修改过于频繁,因此设计的接口能够解决这个问题。另一种是用在哪些不稳定
的部分,如果某些需求的变化性很大,那么定义接口也是一种解决的方法;设计良好的接口就像我们日常使用的万用插座一样不管插头如何变化,
都可以使用。另外一点是良好的接口定义一定是来自于需求,而不是程序员绞尽脑汁想出来的!
三 多态(Polymorphism):就是事物存在的多种体现;
(一)多态的体现:
父类的引用指向了自己的子类,父类的引用页可以接收自己的子类对象;
(二)多态的前提:
(1)继承的存在(继承是多态的基础,没有继承就没有多态)。
(2)子类重写父类的方法(多态下调用子类重写后的方法);
(3)父类引用变量指向子类对象(子类到父类的类型转换);
(三)多态的好处:
(1)提高了程序的扩展性;
(四)多态的应用:
(1)子类到父类的转换(向上转型):Animal d=new Dog();
将 一个父类引用指向一个之类的对象,称为向上转型(upcasting),自动进行类型转换,此时通过父类引用变量掉用的方法是子类覆盖或继承父的
方法 不是父类的方法,但是却无法通过父类的引用调用子类的特有的方法;那么怎么调用子类的特有属性和方法呢,就要向下转型了:
(2)父类到子类的转换(向下转型) Animal d=new Dog(); Dog dog=(Dog)d;
将一个指向子类的对象的父类引用赋给一个子类的引用,称为向下转型,但是要进行强制类型转换:但是在向下转型时如果没有转换为真实的子类
类型就会出现类型转换异常,这有怎么避免呢?这时就要使用java提供的一个运算符了 “instanceof”运算符来进行类型转换;该运算符是用来判断
一个对象是否属于一个类或是一个实现接口,返回值为true 或false;
示例:
public static void main(String[] args) {
// TODO Auto-generated method stub
//子类向上转型将子类引用指向父类
Animal d=new Dog();
Zoo(d);
Animal c=new Cat();
Zoo(c);
}
//创建一个工具方法传入父类对象
public static void Zoo(Animal a){
//使用 instanceof判断是那个之类的对象
if(a instanceof Dog){
//子类向下转型在调用子类的特有的方法
Dog dog=(Dog)a;
dog.eat();
dog.show();
}else if(a instanceof Cat){
Cat c=(Cat)a;
c.eat();
c.show();
}
}
}
class Animal {
public void eat(){
System.out.println("吃的方法!");
}
}
//子类继承父类
class Dog extends Animal{
//子类覆盖父类的方法
public void eat(){
System.out.println("啃骨头!");
}
//子类的特有方法
public void show(){
System.out.println("看家");
}
}
class Cat extends Animal{
//子类覆盖父类的方法
public void eat(){
System.out.println("吃鱼!");
}
//子类的特有方法
public void show(){
System.out.println("抓老鼠");
}
}
(五)弊端:只能使用父类的引用访问父类中的成员;
(六)在多态中成员函数的特点:
在编译时期:参阅引用型变量的类中是否有调用的方法,如果有编译通过,如果没有就编译失败;
在运行时期;参阅对象所属的类中是否有调用的方法;其实就是成员函数在多态调用时,编译看左边,运行看右边;
(七)成员变量的特点:
无论编译还是运行都参考左边(引用型变量所属的类);
-------android培训、java培训、期待与您交流! ----------