山东省建设工会网站,做公司网站的公司,Wordpress和drupal开发,定制网站 报价抽象类
在面向对象的概念中#xff0c;所有的对象都是通过类来描绘的#xff0c;但是并不是所有的类都是用来描绘对象的. 如果一个类中没有包含足够的信息来描绘一个具体的对象#xff0c;这样的类就是抽象类。 抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽…抽象类
在面向对象的概念中所有的对象都是通过类来描绘的但是并不是所有的类都是用来描绘对象的. 如果一个类中没有包含足够的信息来描绘一个具体的对象这样的类就是抽象类。 抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念是对一系列看上去不同但是本质上相同的具体概念的抽象。 比如如果我们进行一个图形编辑软件的开发就会发现问题领域存在着圆、三角形 这样一些具体概念它们是不同的但是它们又都属于形状这样一个概念形状这个概念在问题领域是不存在的它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念所以用以表征抽象概念的抽象类是不能够实例化的。
抽象方法一种特殊的方法它只有声明而没有具体的实现无方法体。抽象方法的声明格式为
abstract void f(); 抽象方法必须用abstract关键字进行修饰。abstract 只能修饰类或类中的成员方法不能修饰属性。被修饰的类或方法分别称作抽象类或抽象方法。其中抽象方法不能有方法体而抽象类不能实例化如果一个类含有抽象方法则这个类一定为抽象类抽象类必须在类前用abstract关键字修饰。当然抽象类也可以没有抽象方法。
abstract class Test1{abstract void f();//正确 抽象方法不能有方法体abstract void g(){;}//编译错 抽象方法不能有方法体void h();//编译错 非抽象类必须有方法体
}【注意】abstract 不能修饰最终方法、静态方法或构造函数因为这三类方法都不能被子类重写。
abstract class Test2{abstract Test2();//编译错 构造函数不能被abstract修饰abstract final void f();编译错 final方法不能被abstract修饰abstract static void g();编译错 静态方法不能被abstract修饰
}抽象类是契约的重量级应用方式接口是契约的轻量级应用方式
接口
Java接口是一系列方法的声明是一些方法特征的集合一个接口只有方法的特征没有方法的实现因此这些方法可以在不同的地方被不同的类实现而这些实现可以具有不同的行为功能。接口可以理解为一种特殊的类里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类既接口中的方法必须全部是抽象方法。 特点
就像一个类一样一个接口也能够拥有方法和属性但是在接口中声明的方法默认是抽象的。即只有方法标识符而没有方法体。接口指明了一个类必须要做什么和不能做什么相当于类的蓝图。一个接口就是描述一种能力比如“运动员”也可以作为一个接口并且任何实现“运动员”接口的类都必须有能力实现奔跑这个动作或者implement move()方法所以接口的作用就是告诉类你要实现我这种接口代表的功能你就必须实现某些方法我才能承认你确实拥有该接口代表的某种能力。如果一个类实现了一个接口中要求的所有的方法然而没有提供方法体而仅仅只有方法标识那么这个类一定是一个抽象类。必须记住抽象方法只能存在于抽象类或者接口中但抽象类中却能存在非抽象方法即有方法体的方法。接口是百分之百的抽象类。
为什么要用接口
接口被用来描述一种抽象。因为Java不像C一样支持多继承所以Java可以通过实现接口来弥补这个局限。接口也被用来实现解耦。接口被用来实现抽象而抽象类也被用来实现抽象为什么一定要用接口呢- 接口和抽象类之间又有什么区别呢原因是抽象类内部可能包含非final的变量但是在接口中存在的变量一定是finalpublic static的。
接口的实现
[修饰符] interface 接口名 [extends 父接口列表]{[public][static][final]类型 成员常量 常量值[public][abstract] 返回类型 成员方法名[参数列表]
}具体的例子 我们知道如果某个设备需要向电脑中读取或者写入某些东西这些设备一般都是采用USB方式与电脑连接的我们发现只要带有USB功能的设备就可以插入电脑中使用了那么我们可以认为USB就是一种功能这种功能能够做出很多的事情实现很多的方法其实USB就可以看做是一种标准一种接口只要实现了USB标准的设备我就认为你已经拥有了USB这种功能。因为你实现了我USB标准中规定的方法。
//先声明USB接口其中规定了要实现USB接口就必须实现接口规定实现的read( )和write( )这两个方法。
interface USB {void read();void write();
}//然后在写一个U盘类和一个键盘类这两个类都去实现USB接口。实现其中的方法
class YouPan implements USB {Overridepublic void read() {System.out.println(U盘正在通过USB功能读取数据);}Overridepublic void write() {System.out.println(U盘正在通过USB功能写入数据);}
}class JianPan implements USB {Overridepublic void read() {System.out.println(键盘正在通过USB功能读取数据);}Overridepublic void write() {System.out.println(键盘正在通过USB功能写入数据);}
}//那么现在U盘和键盘都实现了USB功能也就是说U盘和键盘都能够调用USB接口中规定的方法并且他们实现的方式都不一样。
public class Main {public static void main(String[] args) {//生成一个实现可USB接口标准的U盘对象YouPan youPan new YouPan();//调用U盘的read( )方法读取数据youPan.read();//调用U盘的write( )方法写入数据youPan.write();//生成一个实现可USB接口标准的键盘对象JianPan jianPan new JianPan();//调用键盘的read( )方法读取数据jianPan.read();//调用键盘的write( )方法写入数据jianPan.write();}
}运行结果
U盘正在通过USB功能读取数据
U盘正在通过USB功能写入数据
键盘正在通过USB功能读取数据
键盘正在通过USB功能写入数据【注意】 1接口不是类接口中的方法都是抽象的是没有方法体的没有构造函数也不能实例化出对象。 2一个类可以实现不止一个接口。 3一个接口可以继承于另一个接口或者另一些接口接口也可以继承并且可以多继承。 4一个类如果要实现某个接口的话那么它必须要实现这个接口中的所有方法。 5接口中所有的方法都是抽象的和public的所有的属性都是public,static,final的。 6接口用来弥补类无法实现多继承的局限。 7接口也可以用来实现解耦。
interface A{int x 1;
}
interface B{int y 2;
}
interface C extends A,B{int z 3;
}//也称C为复合接口它有AB两个父接口类中的特殊成员
——内嵌类型、初始化块、本地方法
内嵌类型
内嵌类型就是在类或接口内部定义的自定义类型你包括内部类和内部接口。包围内部类或内部接口的类称为囿类型或包围类型、外部类型等。
class A{ //A是包围类class B{ //内部类int x;}interface C{ //内部接口int y 0;}
}
编译后将产生三个文件A.class、A$B.class、A$C.classinterface X{ //X是包围接口class Y{ //内部类int x;}interface Z{ //内部接口int y 0;}
}
编译后将产生三个文件X.class、X$Y.class、X$Z.class内部类存取规则 1、作为囿类的成员内部类可以存取囿类的其他所有成员包括私有成员。 2、存取内部类及其成员必须要借助囿类或囿类的对象。显然若囿类对象不能访问那么内部类也不能访问。
public class Ch_4_27 {public static void main (String[] args) {Z anew Z();Z.B aba.g(); //★★★借助囿类提供的方法获得内部类对象ab.h2(); //★★★正确可调用内部类的public方法//ab.y6; //编译错不能访问私有成员//A.B ab1new A.B(); //编译错不能以这种方式创建内部类对象//A.B ab1new a.B(); //编译错不能以这种方式创建内部类对象Z.B ab1new Z().new B(); //★★★可用这种方式直接创建内部类对象Z.B ab2a.new B(); //★★★可用这种方式直接创建内部类对象}
}
class Z{public class B{ //内部类定义private int y;private void h1(){x10;} //内部类的成员方法可直接访问囿类的私有成员public void h2(){ //用于测试对外部内部类成员的调用System.out.println(Hi, Executed innerClass Method!); Z.this.x5; //★★★此句显示在内部类中如何引用囿类对象自身}}private int x;private void f(){//y5; //编译错囿类成员方法不能直接访问内部类成员B bnew B(); b.y5; //★★★只能借助内部类对象访问内部类的成员}public B g(){ return new B(); }//返回内部类的实例对象
}1、内部类和囿类可以任意访问没有权限上的限制。但囿类成员方法访问内部类成员必须要借助内部类的对象反之则无此限制。
2、在囿类外部只要权限允许也可以通过囿类对象访问内部类的成员如ab.h2()。但是ab.y6则编译错误因为权限不允许。
3、两种在外部获取内部类对象的方式 1通过囿类的public方法返回如a.g();。 2直接调用内部类的构造函数但方式特殊如new A().new B();或者a.new B();。
静态内部类 Java规定若内部类中有静态成员则该内部类必须是静态内部类。
class A{static class A1{int x; static int y;//正确}class A2{int a ;static int b; //编译错非静态内部类中不能有静态成员}
}
A.A1.y 10;//合法测试静态类和非静态类
成员内部类(可以使用private、default、 protected、 public任意进行修饰。类文件:外部类$内部类.class) a)非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同) i. 非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。 ii. 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。 iii. 非静态内部类不能有静态方法、静态属性和静态初始化块。 iv. 外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。 v. 成员变量访问要点: 1.内部类里方法的局部变量:变量名。 2.内部类属性: this.变量名。 3.外部类属性:外部类名.this.变量名。
public class TestInnerClass {public static void main(String[] args) {//创建内部类对象Outer.Inner inner new Outer().new Inner();inner.show();}
}class Outer{private int age 10;public void testOuter() {System.out.println(Outer.testOuter());}class Inner{int age 20;public void show() {int age 30;System.out.println(外部类的成员变量age:Outer.this.age);System.out.println(内部类的成员变量age:this.age);System.out.println(局部变量age:age);}}
}局部内部类和匿名内部类 成员方法中只有局部变量、常量、内部类相应地称作局部内部类。局部变量不能用权限属性、static、abstract等属性的修饰局部内部类也是如此。局部内部类的作用范围仅限于其所在的方法。
class A{public void f(){int x;class B{int a;public void g(){a x; //编译错误 局部内部类不能引用所在方法中定义的变量。因为局部变量x存于f()的栈空间f运行结束x将自动销毁。但对象存在于堆空间若允许存取x将可能导致错误。}}//局部内部类B b new B();}没有名字的内部类成为匿名类
public class Ch_4_28{public static void main (String[] args) {A anew A() { //定义A的匿名子类匿名的局部内部类 public void f(){System.out.println(匿名类.f());}public void g(){;} //可通过编译但无法使用}; //作为语句结束符的分号不能少匿名类定义结束a.f();// a.g(); //编译错因为a是A类型A中无g()方法}
}
class A{public void f(){ System.out.println(A.f()); }
}初始化块 初始化块就是在类中独立于成员方法之外的代码段它没有名字不带参数无返回值。被static修饰就是静态初始化块否则就是实力初始化块。初始化块的执行遵循以下规则 1初始块的执行顺序遵循其出现的次序。 2实例初始化块先于构造函数。 3静态初始化块在类中的初次加载时执行仅执行一次且先于实例初始化块。
public class Ch_4_29{public static void main(String[] args) {System.out.print(ppppp );new TestBlock(); new TestBlock(99);}
}class TestBlock {TestBlock (int x){System.out.print(1 );}TestBlock (){System.out.print(2 );}static {System.out.print(Static 3 );} //静态初始化块{System.out.print(4 );} //实例初始化块{System.out.print(5 );} //实例初始化块static {System.out.print(Static 6 );} //静态初始化块
}