一个类只定义了一个为全部子类共享的通常形式,至于细节则交给每个子类去实现,这种类没有任何具体的实例,只具备一些抽象的概念,那么这样的类称为抽象类。ide
在面向对象领域,抽象类主要用来进行类型隐藏。好比,若是咱们进行一个图形编辑软件的开发,就会发现问题领域存在着圆、三角形这样一些具体概念,它们是不一样的,可是它们都属于形状这样一个概念,形状这个概念在问题领域是不存在的,它就是一个抽象概念。正是由于抽象概念在问题领域没有对应的具体概念,因此用以表征抽象概念的抽象类是不可以实例化的。模块化
abstract class class_name { abstract type method_name(parameter); }
abstract 表示该类或该方法是抽象的;class_name 表示抽象类的名称;method_name 表示抽象方法名称,若是在一个方法以前使用 abstract 来修饰,则说明该方法是抽象方法,不能有方法体;parameter 表示方法参数列表。this
abstract 关键字只能用于普通方法,不能用于 static 方法或者构造方法中。在抽象类中必须包含至少一个抽象方法,而且全部抽象方法不能有具体的实现,而应在它们的子类中实现全部的抽象方法(要有方法体),包含一个或多个抽象方法的类必须经过在其 class 声明前添加 abstract 关键字将其声明为抽象类。由于一个抽象类不定义完整的实现,因此抽象类也就没有本身的对象。所以,任何使用 new 建立抽象类对象的尝试都会致使编译时错误。设计
public abstract class Shape { public int width; //几何图形的长 public int height; //几何图形的宽 public Shape(int width,int height) { this.width=width; this.height=height; } public abstract double area(); //定义抽象方法,计算面积 } public class Square extends Shape { public Square(int width,int height) { super(width,height); } @Override public double area()//重写父类中的抽象方法,实现计算正方形面积的功能 { return width*height; } } public static void main(String[] args) { Square square=new Square(5,4); System.out.println("面积为:"+square.area());//输出:面积为:20 }
接口相似于类,但接口的成员没有执行体,它只是方法、属性、事件和索引符的组合而已。接口不能被实例化,接口没有构造方法,没有字段。在应用程序中,接口就是一种规范,它封装了能够被多个类继承的公共部分。code
接口继承和实现继承的规则不一样,一个类只有一个直接父类,但能够实现多个接口。Java 接口自己没有任何实现,只描述 public 行为,所以 Java 接口比 Java 抽象类更抽象化。Java 接口的方法只能是抽象的和公开的,Java 接口不能有构造方法,Java 接口能够有 public、Static 和 final 属性。对象
接口把方法的特征和方法的实现分隔开来,这种分隔体如今接口经常表明一个角色,它包装与该角色相关的操做和属性,而实现这个接口的类即是扮演这个角色的演员。一个角色由不一样的演员来演,而不一样的演员之间除了扮演一个共同的角色以外,并不要求其余的共同之处。blog
接口对于其声明、变量和方法都作了许多限制,这些限制做为接口的特征概括以下:
具备 public 访问控制符的接口,容许任何类使用;没有指定 public 的接口,其访问将局限于所属的包。
方法的声明不须要其余修饰符,在接口中声明的方法,将隐式地声明为公有的(public)和抽象的(abstract)。
在 Java 接口中声明的变量其实都是常量,接口中的变量声明,将隐式地声明为 public、static 和 final,即常量,因此接口中定义的变量必须初始化。接口没有构造方法,不能被实例化。继承
public interface interfaceName{ } //例如 public interface Personlnterface{ String name; //不合法,变量name必须初始化 int age=20; //合法,等同于 public static final int age=20; void getInfo(); //方法声明,等同于 public abstract void getInfo(); }
在实现类中,全部的方法都使用了 public 访问修饰符声明。不管什么时候实现一个由接口定义的方法,它都必须实现为 public,由于接口中的全部成员都显式声明为 public索引
public class Person implements Personlnterface { public void getInfo(){ return "Hello World"; } }
public static void main(String[] args){ Personlnterface person = new Person(); person.getInfo();//返回 HelloWorld }
在面向对象的设计思想中,全部的对象都是经过类来描绘的,可是反过来,并非全部的类都是用来描绘对象的,若是一个类中没有描绘一个具体的对象,那么这样的类就是抽象类,抽象类是对那些看上去不一样,可是本质上相同的具体概念的抽象,正是由于抽象的概念在问题领域没有对应的具体概念,因此抽象类是不可以实例化的接口
接口内只能是功能的定义,而抽象类中则能够包括功能的定义和功能的实现。在接口中,全部的属性确定是 public、static 和 final,全部的方法都是 abstract,因此能够默认不写上述标识符;在抽象类中,既能够包含抽象的定义,也能够包含具体的实现方法
public interface Animal { public void eat(); public String fly(); } public abstract class Animal { public abstract void eat(); public String fly(){ return "我会飞"; }; }
接口的实现类中使用 implements 关键字;而在抽象类的实现类中,则使用 extends 关键字。一个接口的实现类能够实现多个接口,而一个抽象类的实现类则只能实现一个抽象类。
//接口 public class concreteAnimal implements Animal { public void eat(){} public void fly(){} } //抽象类 public class concreteAnimal extends Animal { public void eat(){} public void fly(){} }
从前面抽象类的具体实现类的实现方式能够看出,其实在 Java 中,抽象类和具体实现类之间是一种继承关系,也就是说若是釆用抽象类的方式,则父类和子类在概念上应该是相同的。接口却不同,若是采用接口的方式,则父类和子类在概念上不要求相同。接口只是抽取相互之间没有关系的类的共同特征,而不用关注类之间的关系,它可使没有层次关系的类具备相同的行为。所以,能够这样说:抽象类是对一组具备相同属性和方法的逻辑上有关系的事物的一种抽象,而接口则是对一组具备相同属性和方法的逻辑上不相关的事物的一种抽象。
强列的is a 使用抽象类,has a 使用接口。如:鸟是一种动物。鸟有一个功能会飞。猫也是一种动物,可是猫不会飞。
//接口 public interface Fly { public void flyUp(); } //抽象类 public abstract class Animal { public abstract void eat(); } //猫是一种动物 public class Cat extends Animal{ } //鸟是一种动物,同时会飞 public class Bird extends Animal implements Run { }
抽象类是对一组具备相同属性和方法的逻辑上有关系的事物的一种抽象,而接口则是对一组具备相同属性和方法的逻辑上不相关的事物的一种抽象,所以抽象类表示的是“is a”关系,接口表示的是“has a”关系。
在一个类内部的类,咱们称之为内部类。内部类能够很好地实现隐藏,通常的非内部类是不容许有 private 与 protected 权限的,但内部类能够。内部类拥有外围类的全部元素的访问权限。
内部类能够分为:实例内部类、静态内部类和成员内部类,每种内部类都有它特定的一些特色,本节先详细介绍一些和内部类相关的知识。
内部类的特色以下:
内部类仍然是一个独立的类,在编译以后内部类会被编译成独立的 .class 文件,可是前面冠之外部类的类名和 $ 符号。
内部类不能用普通的方式访问。内部类是外部类的一个成员,所以内部类能够自由地访问外部类的成员变量,不管是否为 private 的。
内部类声明成静态的,就不能随便访问外部类的成员变量,仍然是只能访问外部类的静态成员变量。
public class Test { public class InnerClass { public int getSum(int x,int y) { return x+y; } } public static void main(String[] args) { Test.InnerClass testInner =new Test().new InnerClass(); int i = testInner.getSum(2/3); System.out.println(i); //输出5 } }
实例内部类是指没有用 static 修饰的内部类
public class Outer { class Inner { //实例内部类 } }
在外部类的静态方法和外部类之外的其余类中,必须经过外部类的实例建立内部类的实例,若是有多层嵌套,则内部类能够访问全部外部类的成员
public class Outer { class Inner{} Inner i=new Inner(); //类内部不须要建立外部类实例 public void method0() { Inner j=new Inner(); //类内部不须要建立外部类实例 } public static void method1() { Inner r=new Outer().new inner(); //静态方法须要建立外部类实例 } class Inner1 { Inner k=new Inner(); //不须要建立外部类实例 } } class OtherClass { Outer.Inner i=new Outer().new Inner(); //其余类使用时须要建立外部类实例 }
静态内部类是指使用 static 修饰的内部类
public class Outer { static class Inner { //静态内部类 } }
在建立静态内部类的实例时,不须要建立外部类的实例
public class Outer { static class Inner{} } class OtherClass { Outer.Inner oi=new Outer.Inner(); }
局部内部类是指在一个方法中定义的内部类
public class Test { public void method() { class Inner { //局部内部类 } } }
局部内部类与局部变量同样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰,局部内部类只在当前方法中有效,局部内部类中能够访问外部类的全部成员
public class Test { Inner i=new Inner(); //编译出错 Test.Inner ti=new Test.Inner(); //编译出错 Test.Inner ti2=new Test().new Inner(); //编译出错 public void method() { class Inner{} Inner i=new Inner(); } }
匿名类是指没有类名的内部类,必须在建立时使用 new 语句来声明类
new<类或接口>() { //类的主体 };
这种形式的 new 语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口。使用匿名类可以使代码更加简洁、紧凑,模块化程度更高
匿名类有两种实现方式:
继承一个类,重写其方法。
实现一个接口(能够是多个),实现其方法。
public class Out { void show() { System.out.println("调用 Out 类的 show() 方法"); } } public class TestAnonymousInterClass { //在这个方法中构造一个匿名内部类 private void show() { Out anonyInter=new Out() { //获取匿名内部类的实例 void show() { System.out.println("调用匿名类中的 show() 方法"); } }; anonyInter.show(); } public static void main(String[] args) { TestAnonymousInterClass test=new TestAnonymousInterClass(); test.show(); } }