Java内部类、抽象类、泛型和接口 |
您所在的位置:网站首页 › 泛型抽象类 › Java内部类、抽象类、泛型和接口 |
Java内部类、抽象类、泛型和接口
本讲介绍Java面向对象的高级部分。对这一部分内容本文仅作必要而非深入的介绍。 一、Java内部类在Java 语言中的类可以嵌套定义,允许在另外一个类中定义一个类,即在一个类的类体中可以嵌套(nested)定义另外一个类。外层的称为外部类(outer class),也可以叫做封闭类;内部的称为内部类(Inner Classes),有时也称为嵌套类(Nested Class)。内部类可以是静态(static)的,可以使用 public、protected 和 private 访问控制符,而外部类只能使用 public,或者默认。 例如: class OuterClass { // code class InnerClass { // code } } Inner Classes 不能定义为static,不能有static方法和static初始化语句块。 内部类使用场景:当一个类只在某个类中使用,并且不允许除外部类外的其他类访问时,常用于GUI事件监听。 内部类的分类 ☆成员式内部类 ☆局部内部类 ☆匿名内部类 有些人认为内部类的语法很复杂,实际开发中也较少用到,在此仅简要介绍。 成员式内部类 在外部类内部直接定义(不在方法内部或代码块内部)的类就是成员式内部类,它可以直接使用外部类的所有变量和方法,即使是 private 的。外部类要想访问内部类的成员变量和方法,则需要通过内部类的对象来获取。如: public class Outer { private int size; public class Inner { private int counter = 10; public void doStuff() { size++; } } public static void main(String args[]) { Outer outer = new Outer(); Inner inner = outer.new Inner(); inner.doStuff(); System.out.println(outer.size); System.out.println(inner.counter); // 下句编译错误,故注释掉,因为外部类不能访问内部类的变量 //System.out.println(counter); } } 输出: 1 10 注意:必须先有外部类的对象才能生成内部类的对象,因为内部类需要访问外部类中的成员变量,成员变量必须实例化才有意义。 成员式内部类如同外部类的一个普通成员。 成员式内部类可以使用各种修饰符,包括 public、protected、private、static、final 和 abstract,也可以不写。 若有 static 修饰符,就为类级,否则为对象级。类级可以通过外部类直接访问,对象级需要先生成外部的对象后才能访问。 非静态内部类中不能声明任何 static 成员。 内部类可以相互调用,例如: class A { // B、C 间可以互相调用 class B {} class C {} } 局部内部类 局部内部类(Local class)是定义在代码块中的类。它们只在定义它们的代码块中是可见的。 局部类有几个重要特性: 仅在定义了它们的代码块中是可见的; 可以使用定义它们的代码块中的任何局部 final 变量; 局部类不可以是 static 的,里边也不能定义 static 成员; 局部类不可以用 public、private、protected 修饰,只能使用缺省的; 局部类可以是 abstract 的。 例子 public class OuterA { public static final int TOTAL_NUMBER = 5; public int id = 123; public void func() { final int age = 15; String str = "测试"; class Inner { public void innerTest() { System.out.println(TOTAL_NUMBER); System.out.println(id); // System.out.println(str);不合法,只能访问本地方法的final变量 System.out.println(age); } } new Inner().innerTest(); } public static void main(String[] args) { OuterA OuterA = new OuterA(); OuterA.func(); } } 运行结果: 5 123 15 匿名内部类 匿名内部类是局部内部类的一种特殊形式,也就是没有变量名指向这个类的实例,而且具体的类实现会写在这个内部类里面。 注意:匿名类必须继承一个父类或实现一个接口。 例子 abstract class PersonOne { public abstract void eat(); } class Child extends PersonOne { public void eat() { System.out.println("eat something"); } } public class DemoOne { public static void main(String[] args) { PersonOne p = new Child(); p.eat(); } } 运行结果: eat something Java内部类更多介绍,可参见 https://blog.csdn.net/cnds123/article/details/130627538 二、抽象类java语言中,用abstract 关键字来修饰一个类时,这个类叫作抽象类。 普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法,普通方法,static方法,常量和变量等内容。而抽象类除了含有普通类的成员,必须含有抽象方法。 那么什么叫抽象方法呢?在所有的普通方法上面都会有一个"{}",这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指,没有方法体的方法,且抽象方法必须被abstract关键字所修饰。 拥有抽象方法体的类就被成为抽象类,抽象类必须使用abstract关键字所修饰,如果一个类包含抽象方法,所以该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象方法。 抽象类的定义使用abstract关键字,抽象方法也使用abstract关键字进行修饰。如果一个类包含抽象方法,则该类必须声明为抽象类。 下面给出一个简单示例源码: abstract class AnimalsDemo{ String name = "猫咪"; abstract void eat(); } class Cats extends AnimalsDemo{ @Override void eat() { System.out.println(name + "正在吃饭"); } } public class TestB { public static void main(String[] args) { Cats cats = new Cats(); cats.eat(); //猫咪正在吃饭 } } 抽象类不能创建对象,如果硬要创建,会出现编译报错。 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类使用的。 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类,不包含抽象方法的抽象类,目的就是不想让调用者实例化该对象,通常用于某些特殊的类的结构设计。 抽象类的子类,必须重写抽象父类的所有抽象方法,否则会出现编译报错,除非该子类也是抽象类(假设不重写父类中所有的抽象方法,那么调用抽象方法毫无意义)。 Java中的抽象类更多介绍,可参见 https://blog.csdn.net/cnds123/article/details/130618011 三、泛型所谓“泛型”,就是“宽泛的数据类型”,任意的数据类型。 假如我们现在要定义一个类来表示坐标,要求坐标的数据类型可以是整数、小数和字符串,例如: x = 10、y = 10 x = 12.88、y = 129.65 x = "东京180度"、y = "北纬210度" 针对不同的数据类型,除了借助方法重载,还可以借助自动装箱和向上转型。我们知道,基本数据类型可以自动装箱,被转换成对应的包装类;Object 是所有类的祖先类,任何一个类的实例都可以向上转型为 Object 类型,例如: int --> Integer --> Object 还可以使用泛型类。 泛型类声明格式为: class 类名 如:class A 其中,A是泛型类的名称,E、F是泛型类的参数,即泛型类的参数类型没有指定。它可以是任何引用类型,但不能是基本数据类型。 例子 public class DemoGeneric { public static void main(String[] args){ // 实例化泛型类 PointOne p1 = new PointOne(); p1.setX(10); p1.setY(20); int x = p1.getX(); int y = p1.getY(); System.out.println("This Point is:" + x + ", " + y);
PointOne p2 = new PointOne(); p2.setX(25.4); p2.setY("东京180度"); double m = p2.getX(); String n = p2.getY(); System.out.println("This Point is:" + m + ", " + n); } } // 定义泛型类 class PointOne{ T1 x; T2 y; public T1 getX() { return x; } public void setX(T1 x) { this.x = x; } public T2 getY() { return y; } public void setY(T2 y) { this.y = y; } } 运行结果: This point is:10, 20 This point is:25.4, 东京180度 上面的代码在类名后面多出了 ,T1, T2 是自定义的标识符,也是参数,用来传递数据的类型,而不是数据的值,我们称之为类型参数。在泛型中,不但数据的值可以通过参数传递,数据的类型也可以通过参数传递。T1, T2 只是数据类型的占位符,运行时会被替换为真正的数据类型。 传值参数(我们通常所说的参数)由小括号包围,如 (int x, double y),类型参数(泛型参数)由尖括号包围,多个参数由逗号分隔,如 或 。 类型参数需要在类名后面给出。一旦给出了类型参数,就可以在类中使用了。类型参数必须是一个合法的标识符,习惯上使用单个大写字母,通常情况下,K 表示键,V 表示值,E 表示异常或错误,T 表示一般意义上的数据类型。 泛型类在实例化时必须指出具体的类型,也就是向类型参数传值,格式为: className variable = new className(); 注意: 泛型是 Java 1.5 的新增特性,它以C++模板为参照,本质是参数化类型(Parameterized Type)的应用。 类型参数只能用来表示引用类型,不能用来表示基本类型,如 int、double、char 等。但是传递基本类型不会报错,因为它们会自动装箱成对应的包装类。 Java中的泛型更多介绍,可参见 https://blog.csdn.net/cnds123/article/details/130605741 四、Java接口(interface)接口(Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。 接口就是比“抽象类"还“抽象”的“抽象类”, 可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。接口是完全面向规范的,规定了一批类具有的公共方法规范。 从接口的实现者角度看,接口定义了可以向外部提供的服务。 从接口的调用者角度看,接口定义了实现者能提供那些服务。 接口是两个模块之间通信的标准,通信的规范。如果能把你要设计的模块之间的接口定义好,就相当于完成了系统的设计大纲,剩下的就是添砖加瓦的具体实现了。大家在工作以后,做系统时往往就是使用“面向接口”的思想来设计系统。 接口和实现类不是父子关系,是实现规则的关系。 接口主要特点: 1、接口不能实例化对象 可以用来声明引用变量的类型 2、一个类实现一个接口,那么必须实现这个接口中定义的所有方法,并且只能是public 3、jdk1.7以及之前 接口中只能有方法的定义 jdk1.8之后可以有default(虚拟扩展方法)和静态方法 抽象类和接口的区别 接口 抽象类 不考虑java8中default方法的情况下,接口中是没有实现代码的实现 抽象类中可以有普通成员方法 ,并且可以定义变量 接口中的方法修饰符号 只能是public 抽象类中的抽象方法可以有public,protected,default 接口中没有构造方法 可以有构造方法 接口和抽象类如何选择: 1、当我们需要一组规范的方法的时候,我们就可以用接口,在具体的业务中,来对接口进行实现,能达到以不变应对万变,多变的需求的情况我们只需要改变对应的实现类 。 2、如果多个实现类中有者相同可以复用的代码 这个时候就可以在实现类和接口之间,添加一个抽象类,把公共的代码抽出在抽象类中。然后要求不同实现过程的 子类可以重写抽象类中的方法,来完成各自的业务。 接口的定义(声明)语法格式如下: [访问修饰符号] interface 接口名称 [extends 父接口1[,父接口2, ...]] { 常量定义: 方法定义: } 访问修饰符:只能是public 或者默认 extends:接口支持多继承 接口中的数据成员只能是常量,默认就是public static finnal 接口中的方法默认是public abstract 换句话说,接口有以下特性: 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键子。 接口中的方法都是公有的。 一个接口,可以拥有N个直接的父接口,如: interface A { … } interface B { … } interface C { … } //一个接口,可以拥有N个直接的父接口 public interface D extends A,B,C { … } 接口的实现 当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。 使用implements关键字实现接口,接口实现的语法: 类修饰符 class 类名称 implements 接口名称1[, 接口名称2, ...] { ... } 下面给出一个例子,代码如下: //用interface声明两个接口 interface Person { void say(); } interface Parent { void work(); } //用implements实现两个接口 class Child implements Person, Parent { public void work() { System.out.println("学习"); } public void say() { System.out.println("Child"); } } public class TestImplements{ public static void main(String[] args) { Child c = new Child(); c.say(); c.work(); } } 运行输出结果: Child 学习 下面再给出一个例子,代码如下: //创建一个接口名字为Abc interface Abc { //创建接口方法getMax public int getMax(); //创建接口方法getMes public String getMes(); } //test2类描述的是实现接口的方法 class test2 implements Abc{ //实现接口里的方法 public int getMax() { //定义int类型的私有变量i int i = 123; //将变量i返回出去并退出方法 return i; } //实现接口里的方法 public String getMes() { //定义String类型的私有变量s String s = "实现接口里的方法"; //将变量s返回出去并退出方法 return s; } } public class TestImplements2{
//main方法为Java程序的入口方法 public static void main(String args[]) { //创建test类的对象实例,引用为t test2 t = new test2();
//实现了接口里的方法并进行调用 int i = t.getMax(); String s = t.getMes();
//打印并显示结果 System.out.println(i); System.out.println(s); } } 运行输出结果: 123 实现接口里的方法 Java接口更多介绍,可参见 https://blog.csdn.net/cnds123/article/details/130618885 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |