Java进阶知识体系 (一)、类和对象 (二)、方法和封装 (三)、static关键字和继承 (四)、多态 (五)、特殊类
(五)、特殊类 1,抽象类 抽象类的概念 抽象类主要指不能具体实例化的类并且使用abstract关键字修饰,也就是不能创建对象
抽象方法的概念 抽象方法主要指不能具体实现的方法并且使用abstract关键字修饰,也就是没有方法体。 具体格式如下: 访问权限 abstract 返回值类型 方法名(形参列表); public abstract void cry();
抽象类和抽象方法的关系 抽象类中可以有成员变量、构造方法、成员方法; 抽象类中可以没有抽象方法,也可以有抽象方法; 拥有抽象方法的类必须是抽象类,因此真正意义上的抽象类应该是具有抽象方法并且使用abstract关键字修饰的类。
抽象类的实际意义 抽象类的实际意义不在于创建对象而在于被继承。 当一个类继承抽象类后必须重写抽象方法,否则该类也变成抽象类,也就是抽象类对子类具有强制性和规范性,因此叫做模板设计模式。
开发经验分享 在以后的开发中推荐使用多态的格式,此时父类类型引用直接调用的所有方法一定是父类中拥有的方法,若以后更换子类时,只需要将new关键字后面的子类类型修改而其它地方无需改变就可以立即生效,从而提高了代码的可维护性和可扩展型。 该方式的缺点就是:父类引用不能直接调用子类独有的方法,若调用则需要强制类型转换
抽象类的应用 银行有 定期账户和活期账户。继承自 账户类。账户类中: public class Account{ private double money; public double getLixi(){} }
2,接口 接口的基本概念 接口就是一种比抽象类还抽象的类,体现在所有方法都为抽象方法。 定义类的关键字是class,而定义接口的关键字是interface。 如:金属接口 货币接口 黄金类
类和接口之间的关系 抽象类和接口的主要区别(笔试题) 定义抽象类的关键字是abstract class,而定义接口的关键字是interface。 继承抽象类的关键字是extends,而实现接口的关键字是implements。 继承抽象类支持单继承,而实现接口支持多实现。 抽象类中可以有构造方法,而接口中不可以有构造方法。 抽象类中可以有成员变量,而接口中只可以有常量 抽象类中可以有成员方法,而接口中只可以有抽象方法。 抽象类中增加方法时子类可以不用重写,而接口中增加方法时实现类需要重写(Java8以前的版本);从Java8开始增加新特性,接口中允许出现非抽象方法和静态方法,但非抽象方法需要使用default关键字修饰;从Java9开始增加新特性,接口中允许出现私有方法。
3,内部类 内部类的基本概念 当一个类的定义出现在另外一个类的类体中时,这个类叫做内部类(Inner),而内部类所在的类叫做外部类(Outer)。
类中的内容 成员变量、成员方法、构造方法、静态成员、构造块和静态代码块、内部类。
内部类实际作用 当一个类存在的价值仅仅是为某一个类单独服务时,那么就可以将这个类定义为所服务类中的内部类,这样可以隐藏该类的实现细节并且可以方便的访问外部类的私有成员而不再需要提供公有的get和set方法。
内部类的分类 普通内部类 – 直接将一个类的定义放在另外一个类的类体中。 静态内部类 – 使用static关键字修饰的内部类,隶属于类层级。 局部内部类 – 直接将一个类的定义放在方法体的内部时。 匿名内部类 – 就是指没有名字的内部类。
普通(成员)内部类的格式 访问修饰符 class 外部类的类名 { 访问修饰符 class 内部类的类名 { 内部类的类体; } }
普通内部类的使用方式 普通内部类和普通类一样可以定义成员变量、成员方法以及构造方法等。 普通内部类和普通类一样可以使用final或者abstract关键字修饰。 普通内部类还可以使用private或protected关键字进行修饰。 普通内部类需要使用外部类对象来创建对象。 如果内部类访问外部类中与本类内部同名的成员变量或方法时,需要使用this关键字。
访问特点 成员内部类可以直接访问外部类的成员变量和成员方法 外部类不可以直接访问内部类的成员变量和成员方法
外部类名.内部类名 对象名 = new 外部类名().new 内部类名(); class Outer{ private int x = 10; class Inner{ public void test(){ System.out.println(x); } } } class Test{ public static void main(String[] args){ //创建内部类对象 : 外部类名.内部类名 内部类对象名 = 外部类对象.内部类对象. Outer.Inner in = new Outer().new Inner(); in.test();
}
静态内部类的格式 访问修饰符 class 外部类的类名 { 访问修饰符 static class 内部类的类名 { 内部类的类体} }
静态内部类的使用方式 静态内部类不能直接访问外部类的非静态成员。 静态内部类可以直接创建对象。 如果静态内部类访问外部类中与本类内同名的成员变量或方法时,需要使用类名.的方式访问。
外部类名.内部类名 内部类对象名 = new 外部类名.内部类对象; class Outer { static class Inner { public static void method(){ Systme.out.println(“abc”); } } class Test{ public static void main(String[] args){ Outer.Inner in = new Outer.Inner(); 如果方法也是静态: Outer.Inner.method(); in.method(); } }
局部(方法)内部类的格式 访问修饰符 class 外部类的类名 { 访问修饰符 返回值类型 成员方法名(形参列表) { class 内部类的类名 { 内部类的类体; } } }
局部内部类的使用方式 局部内部类只能在该方法的内部可以使用。 局部内部类可以在方法体内部直接创建对象。 局部内部类不能使用访问控制符和static关键字修饰符。 局部内部类可以使用外部方法的局部变量,但是必须是final的。由局部内部类和局部变量的声明周期不同所致。 问题显现: //Test2.java:8: 错误: 从内部类中访问本地变量x; 需要被声明为最终类型 class Outer { //方法 public void method(){ final int x = 10; // 常量 (方法区的常量池—-> 生命周期变量) //局部内部类 class Inner { public void test(){ System.out.println(x); //局部内部类要访问局部变量, 那么该局部变量需要是被final修饰的. } } } }
回调模式的概念 回调模式是指——如果一个方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象;而该方法在运行时会调用到参数对象中所实现的方法(接口中定义的)
开发经验分享 当接口/类类型的引用作为方法的形参时,实参的传递方式有两种; 自定义类实现接口/继承类并重写方法,然后创建该类对象作为实参传递; 使用上述匿名内部类的语法格式得到接口/类类型的引用即可;
匿名内部类的语法格式(重点) 概念: 一个继承了类的子类的匿名对象 或者一个实现了接口的实现类的匿名对象。 条件: 匿名内部类必须继承一个父类或者实现一个父接口。
格式: 接口/父类类型 引用变量名 = new 接口/父类类型() { 方法的重写 }; 例子: new 父类名或者接口名(){ // 方法重写 @Override public void method() { // 执行语句 } }; 实现例子: public class NoNameClassTest { public static void main(String[] args) { /* * In的子类对象 , 再调用play() */ new In(){ public void play() { System.out.println(“玩游戏”); } }.play(); } } interface In{ void play(); }
4,枚举 枚举的基本概念 一年中的所有季节:春季、夏季、秋季、冬季。 在日常生活中这些事物的取值只有明确的几个固定值,此时描述这些事物的所有值都可以一一列举出来,而这个列举出来的类型就叫做枚举类型。
枚举的定义 使用public static final表示的常量描述较为繁琐,使用enum关键字来定义枚举类型取代常量,枚举类型是从Java5开始增加的一种引用数据类型。 枚举值就是当前类的类型,也就是指向本类的对象,默认使用public static final关键字共同修饰,因此采用枚举类型.的方式调用。 枚举类可以自定义构造方法,但是构造方法的修饰符必须是private,默认也是私有的
举例 public enum Direction { FRONT, BEHIND, LEFT, RIGHT; } Direction d = Direction.FRONT;
枚举注意事项 1)定义枚举类的关键字是enum,而不是Enum,所有关键字都是小写的! 其中FRONT、BEHIND、LEFT、RIGHT都是枚举项,它们都是本类的实例,本类一共就只有四个实例对象。 在定义枚举项时,多个枚举项之间使用逗号分隔,最后一个枚举项后需要给出分号!但如果枚举类中只有枚举项(没有构造器、方法、实例变量),那么可以省略分号!建议不要省略分号! 2)不能使用new来创建枚举类的对象,因为枚举类中的实例就是类中的枚举项,所以在类外只能使用类名.枚举项。
枚举类实现接口的方式 枚举类实现接口后需要重写抽象方法,而重写方法的方式有两种:重写一个,或者每个对象都重写。
枚举成员 其实枚举类和正常的类一样,可以有实例变量,实例方法,静态方法等等,只不过它的实例个数是有限的,不能再创建实例而已
5,注解 注解的基本概念 注解(Annotation)又叫标注,是从Java5开始增加的一种引用数据类型。 注解本质上就是代码中的特殊标记,通过这些标记可以在编译、类加载、以及运行时执行指定的处理。
注解的语法格式 访问修饰符 @interface 注解名称 { 注解成员; } 自定义注解自动继承java.lang.annotation.Annotation接口。 通过@注解名称的方式可以修饰包、类、 成员方法、成员变量、构造方法、参数、局部变量的声明等。
注解的使用方式 注解体中只有成员变量没有成员方法,而注解的成员变量以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。 如果注解只有一个参数成员,建议使用参数名为value,而类型只能是八种基本数据类型、String类型、Class类型、enum类型及Annotation类型。
定义注解 public @interface MyTestAnnotation { }
使用注解 @MyTestAnnotation public class test { @MyTestAnnotation public static void main(String[] args){ } }
注解本质 注解的本质就是一个Annotation接口
注解属性 注解属性类型可以有以下列出的类型 1.基本数据类型 2.String 3.枚举类型 4.注解类型 5.Class类型 6.以上类型的一维数组类型
获取注解属性 /*是否存在对应 Annotation 对象/ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { return GenericDeclaration.super.isAnnotationPresent(annotationClass); }
/*获取 Annotation 对象/ public A getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass);
return (A) annotationData().annotations.get(annotationClass);
}
/*获取所有 Annotation 对象数组/ public Annotation[] getAnnotations() { return AnnotationParser.toArray(annotationData().annotations); }
元注 解的概念 元注解是可以注解到注解上的注解,或者说元注解是一种基本注解,但是它能够应用到其它的注解上面。 元注解主要有 @Retention、@Documented、@Target、@Inherited、 @Repeatable。
元注解@Retention @Retention 应用到一个注解上用于说明该注解的的生命周期,取值如下: RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中,默认方式。 RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
元注解@Documented 使用javadoc工具可以从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档,而该工具抽取时默认不包括注解内容。 @Documented用于指定被该注解将被javadoc工具提取成文档。 定义为@Documented的注解必须设置Retention值为RUNTIME。
元注解@Target @Target用于指定被修饰的注解能用于哪些元素的修饰,取值如下: ElementType.ANNOTATION_TYPE 可以给一个注解进行注解 ElementType.CONSTRUCTOR 可以给构造方法进行注解 ElementType.FIELD 可以给属性进行注解 ElementType.LOCAL_VARIABLE 可以给局部变量进行注解 ElementType.METHOD 可以给方法进行注解 ElementType.PACKAGE 可以给一个包进行注解 ElementType.PARAMETER 可以给一个方法内的参数进行注解 ElementType.TYPE 可以给类型进行注解,比如类、接口、枚举
元注解@Inherited @Inherited并不是说注解本身可以继承,而是说如果一个超类被该注解标记过的注解进行注解时,如果子类没有被任何注解应用时,则子类就继承超类的注解
元注解@Repeatable @Repeatable表示自然可重复的含义,从Java8开始增加的新特性。 从Java8开始对元注解@Target的参数类型ElementType枚举值增加了两个: 其中ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中,如:泛型。 其中ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中。
常见的预制注解 预制注解就是Java语言自身提供的注解,具体如下: @author 标明开发该类模块的作者,多个作者之间使用,分割 @version 标明该类模块的版本 @see 参考转向,也就是相关主题 @since 从哪个版本开始增加的 @param 对方法中某参数的说明,如果没有参数就不能写 @return 对方法返回值的说明,如果方法的返回值类型是void就不能写 @exception 对方法可能抛出的异常进行说明
常用的预制注解 @Override 限定重写父类方法, 该注解只能用于方法 @Deprecated 用于表示所修饰的元素(类, 方法等)已过时 @SuppressWarnings 抑制编译器警告
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/2105.html