目录
抽象类(abstract)
-
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
-
抽象类中可以没有抽象方法,但是由有抽象方法的类一定要声明抽象类。
-
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。但是有构造方法供子类使用。(super)
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
-
子类继承抽象类,就必须将抽象类中抽象方法实现,否则该子类也要声明为抽象类。
-
abstract 和 final是对立的
-
//abstract 抽象类:类 extends : 单继承~ 接口可多继承
public abstract class Action {
//约束 有人帮我们实现~
//abstract,抽象方法,只有方法名字,没有方法的实现
public abstract void doSomething();
//1.不能new这个抽象类,只能靠子类实现它:约束!
//2.抽象类中可以写普通方法
//3.抽象方法必须在抽象类中
//抽象的抽象:约束
//抽象类存在的意义是什么?
//---防止重复代码,提高开发效率。后期通过子类拓展,提高后期可拓展性
}
//Action抽象类的所有方法,A类都继承它的类,且都必须要实现它的方法,除非,它的子类也是abstract类,就让它的子子类来实现
public class A extends Action {
@Override
public void doSomething() {
}
}
接口(interface)
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有!
-
接口:只有规范。 约束和分离:面向接口编程
-
声明类的关键字是class,声明接口的关键字是interface,implements接口实现
-
实现的接口必须要重写接口中的方法。
-
如果一个类同时继承父类和实现接口,extends 在前,implements在后
//interface 定义的关键字 , 接口都需要实现类
public interface UserService {
//接口定义的属性都是静态常量(默认:public static final)
public static final int AGT = 99;
//接口中的所有定义其实都是默认抽象的 public abstract
//public abstract void add(String name);
void add(String name); //增删改查
void delete(String name);
void update(String name);
void query(String name);
//JDK8之后
//缺省方法-扩展方法: 后代实现类可以重写此方法也可以不重写 方便扩展
default void testDefault(){
System.out.println("缺省方法...");
}
//静态方法 -静态方法一般都是一些工具类中定义的功能方法
(有了collection,collections就没必要了)
static void tetstStatic(){
System.out.println("静态方法...");
}
//JDK9之后
//私有方法: 供本接口中缺省方法和静态方法使用
private void testPrivae(){
System.out.println("私有方法...");
}
}
public interface TimeService {
void timer();
}
//抽象类: extends
//类 可以实现接口 imlements 接口
//实现了接口的类,就需要重写接口的方法
//多继承,利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
//
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
//多继承
@Override
public void timer() {
}
}
-
接口就是规范,定义是一组规则,体现了显示中“如果你是...则必须能...”的思想
-
接口的本质是契约,就像法律一样,必须去遵守。
-
OOP的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式只针对具备了抽象能力的语言(比如c++,java,c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。降低耦合度,提高扩展性
内部类(Inner Class)
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了
如果在局部内部类中使用了所在方法的局部变量,则此局部变量会被final修饰;(Lambda表达式)
-
成员内部类、静态内部类、局部内部类
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
-
静态内部类
public class Outer {
private int id = 10;
public static class Inner{
//静态内部类无法访问外部类非静态的属性
//因为静态类在外部类之前初始化
}
}
-
局部内部类
为什么在局部内部类中使用外部类方法的局部变量要加final呢?
public class TestInner{
public static void main(String[] args) {
A obj = Outer.method();
//因为如果c不是final的,那么method方法执行完,method的栈空间就释放了,那么c也就消失了
obj.a();//这里打印c就没有值可取了,所以把c声明为常量,存储在方法区中
}
}
interface A{
void a();
}
class Outer{
public static A method(){
final int c = 3;
class Sub implements A{
@Override
public void a() {
System.out.println("method.c = " + c);
}
}
return new Sub();
}
}
-
匿名内部类:局部的一种,不建议使用,类没有名字无法重复使用,可读性差。
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中
new Apple().eat();//匿名局部类 没有变量名
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
注解(annotation)
- 注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据
三种常见注解
- @Override:用于标识方法,标识该方法属于重写父类的方法
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
- @Deprecated:用于标识方法或类,标识该类或方法已过时,建议不要使用
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
- @SuppressWarnings:用于关闭编译器对类、方法、成员变量、变量初始化的警告
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
元注解
元注解,即修饰注解的注解,定义注解时使用
- 自定义注解
@Target(ElementType.FIELD) //用在什么地方 Field字段
@Retention(RetentionPolicy.SOURCE) //作用域 源代码
public @interface MyAnno {
int max() default 0;
int min() default 0;
String description() default"";
}
作用 -- 功能未知,需配合反射使用
class Student{
@MyAnno(min = 6,max = 10,description = "用户名长度在6-10个字符之间")
private String name;
@MyAnno(min = 6,max = 10,description = "用户名长度在6-10个字符之间")
private String pasdword;
public Student(String name, String pasdword) {
this.name = name;
this.pasdword = pasdword;
}
}
//配合反射实现:根据用户设置属性长度检查属性值是否符合要求