Abstract抽象类

1.抽象类不能被实例化

2.抽象方法没有方法体

如:

public abstract class Weapen
{
public abstract void attack();
  • 抽象类中可以没有抽象方法,但若有了抽象方法,该类就必须是抽象类
  • abstract和static不能连用,为什么呢?请往下看……
  • 抽象类虽然不能被实例化,但是能创建一个引用变量,类型是抽象类,引用非抽象类的具体子类的一个实例。
abstract class Weapon
{
public abstract void attack();
} public class Sword extends Weapon
{
public void attack()
{
//do sth.
} public static void main(String args[])
{
//Weapon w1 = new Weapon(); //error Weapon w2 = new Sword(); //ok
}
}

Sword.java

final

  • final修饰的类不允许被继承,即没有子类,断后了。
  • final修饰的方法不能被子类的方法覆盖。
  • final修饰的变量表示常量,只允许被赋值一次。
  • final类型的实例变量,要么在定义变量的时候初始化,要么在构造方法中初始化。

  (假如有多个构造函数,每一个构造函数都要初始化final变量,否则会出现编译错误“错误: 可能尚未初始化变量”)

  • final类型的静态变量,只能在定义变量的时候初始化。

Static

由于静态方法不需要通过实现实例就可以被调用,所以在静态方法中不能使用this关键字(它不知道this指的是谁,因为没有实例);也不能直接访问实例变量和实例方法(没有实例哪来的实例变量和实例方法);但是可以直接访问静态变量和静态方法。

静态方法必须被实现,为什么

因为静态方法不依赖类的实例而存在,所以当前类必须为静态方法提供实现,换句话说,一个静态的方法不能定义为抽象的方法。即static和abstract不能同时使用。

public class Test
{
int x;//x是一个实例变量,不能被静态方法直接访问 Test()
{
x = ;
} public static void main(String[] args)
{
System.out.println(x);
}
}

错误的Test.java

public class Test
{
int x; Test()
{
x = 1;
} public static void main(String[] args)
{
Test t1 = new Test(); System.out.println(t1.x);
}
}

正确的Test.java

接口

Seller.java

interface Cal_Int    //接口
{
double mul(double a, double b); //public abstract
} class Cal implements Cal_Int //实现接口的类
{
public double mul(double a, double b) //must public
{
return a*b;
}
} class Seller
{
Cal_Int cal; public Seller(Cal_Int cal)
{
this.cal = cal;
} public void compute(double price, double amount)
{
System.out.println(cal.mul(price, amount));
} public static void main(String[] args)
{
Cal_Int cal = new Cal(); //定义接口类型的引用变量,引用了实现该接口的类的实例 Seller seller = new Seller(cal); seller.compute(0.1, 16);
}
}

通俗来讲,接口就是一个类似抽象类的东西。

如果一个类需要用到接口,那么该类只需按照接口给出的函数调用即可,而不关心它是怎么实现的(就像调用API一样)

如果一个类需要实现接口,那么该类就要覆盖(override)接口给出的函数。(Android中的implements OnClickListener,然后重写onClick函数)

  • 接口中的成员变量默认且必须是public, static, final,必须被显示初始化。
  • 接口中的方法默认且必须是public abstract。
  • 接口没有构造方法。
public interface A
{
public static final CONST2 = 2; int CONST = 1; //ok 默认是public static final int var; //error static未显示初始化 接口中也没有构造方法可以初始化 void f(); //ok 默认是public, abstract void f2(){}; //error 必须是abstract protected void f3();//error 必须是public public A(){} //error 接口中没有构造方法,因为没有实例
}
  • 一个接口不能实现另一个接口,但是可以继承多个接口。
  • 一个类只能继承一个父亲,但可以实现多个接口。
  • 接口必须通过类来实现它的抽象方法。
  • 当类实现接口的时候,必须实现接口中的所有方法,否则它将被定义为抽象类(不然就含有Abstract方法,那就必须是抽象类)。
  • 不能直接创建接口的实例,但是可以定义接口类型的引用变量,该变量引用实现了该接口的类的实例(好好理解下这句话,不懂的话见上面Seller.java)。

this与super

Monkey.java

public class Monkey
{
private String name; private int age; public Monkey(String name, int age)
{
this.name = name; this.age = age;
} public Monkey(String name) //缺省age的时候
{
this(name, -1); //ok //Monkey(name, -1); //error 不能通过类名来调用
} public Monkey(int age) //缺省name的时候
{
this("Anonymous", age);
} public Monkey()
{
this("Anonymous", -1); //缺省name和age的时候
}
}
  • 同一个类中,在一个构造方法中,可以通过使用this来调用另一个重载的构造方法。而不能使用类名来调用,这点很重要。
  • this语句必须放在构造方法中的第一句。

Sub.java

class Base
{
Base(int i)
{
System.out.println(i);
}
} public class Sub extends Base
{
Sub(int i)
{
super(i);
} Sub()
{
super(0);
} public static void main(String[] args)
{
Sub sub = new Sub(); Sub sub2 = new Sub(1);
}
}

子类调用父类的构造方法一共有2种方式,一种是用super,另一种不使用super,系统自动调用父类的默认构造方法。

  • 子类的构造方法中不能使用父类名字来调用父类的构造方法,而要使用super语句。
  • super语句必须放在子类构造方法中的第一句。

内部类

内部类:在一个类的内部定义的类就称为内部类。

内部类可以有4种访问级别:public,protected,默认和private。

顶层类(最外层的类)只能有2种访问级别:public和默认。(你什么时候见过最外层的类有protected和private修饰)

类内:

变量可以分为局部变量和成员变量,成员变量可以分为静态变量和实例变量。

内部类可以分为局部内部类和成员内部类,成员内部类可以分为静态内部类和实例内部类。

局部内部类:

局部内部类不能用public、protected、private和static修饰。

局部内部类可以直接访问外部类的所有成员以及所在方法中的final参数和变量。

class A
{
int a; public void f(final int p1, int p2)
{
final int v1 = 2;
int v2 = 1; class B
{
int b1 = a; //ok
int b2 = p1; //ok
int b3 = p2; //error
int b4 = v1; //ok
int b5 = v2; //error
}
}
}

实例内部类:

1.

public class A
{
public class B
{
} private B b = new B(); //类内直接访问B
} A.B b = new A().new B(); //类外访问要确保类名完整

这个例子中,内部类B的完整类名为A.B。若在类内,可以直接访问;若在类外,访问时类名要完整。

最后一句等价于

A a = new A();
A.B b = a.new B();

2.实例内部类可以直接访问外部类的所有成员变量和方法(任何级别的都可以)

为什么呢,因为当内部类B的实例存在的时候,它的外部类A的实例必定也存在,因此可以访问到。

可以设想一个儿子诞生的时候,必定有母亲的存在,所以他可以持有母亲有的东西。

3.外部类不能直接访问实例内部类的成员变量和方法,但可以访问实例内部类的实例的成员变量和方法。

这样理解,若一个母亲可能没有儿子,那这个时候怎么拿到儿子的东西呢?但是若是先创建了一个儿子,那么这个时候母亲就可以拿到了。

public class A
{
public class B
{
int x = 0;
} public void f()
{
int v1 = x; //error 万一内部类的实例没有创建呢 B b = new B(); int v2 = b.x; //ok 通过实例去访问
}
}

静态内部类:

静态内部类用static修饰,不同于实例内部类,静态内部类的实例不依赖于外部类实例的存在。

1.创建静态内部类时,不需要创建外部类的实例。

public class A
{
public static class B
{
int x = 0;
}
} A.B b = new A.B();
b.x = 2;

2.静态内部类可以直接访问外部类的静态成员,如果要访问实例成员,只能通过外部类的实例去访问。

public class A
{
int a1;
static int a2; public static class B
{
int b1 = a1; //error int b2 = a2; //ok int b3 = new A().a1; //ok
}
}

3.可以通过完整的类名去访问静态内部类的静态成员。

public class A
{
public static class B
{
int v1; static int v2;
}
} A.Bb = new A.B();
b.v1 = 1; //ok
b.v2 = 2; //ok
A.B.v1 = 1; //error
A.B.v2 = 2; //ok

匿名类:

匿名类:没有名字的内部类

public class A
{
A()
{
System.out.println("Default Constructor");
} A(int v)
{
System.out.println("Special Constructor");
} void f()
{
System.out.println("from A");
} public static void main(String[] args)
{
new A().f(); A a = new A() //定义了一个继承A的匿名类
{
void f(){System.out.println("from anonymous");}//覆盖父类A的方法
}; a.f();
}
}

输出结果是

Default Constructor
from A
Default Constructor
from anonymous

这个语句

A a = new A()    //定义了一个继承A的匿名类
{
void f(){System.out.println("from anonymous");}//覆盖父类A的方法
};

定义了一个继承A的匿名类。相当于

class Sub extends A
{
void f(){System.out.println("from anonymous");}//覆盖父类A的方法
}
A a = new Sub();

所以这种情况可以看作是没有名字的子类。

1.匿名类本身没有构造方法,但会自动调用父类的构造方法。

public class A
{
A()
{
System.out.println("Default Constructor");
} A(int v)
{
System.out.println("Special Constructor");
} void f()
{
System.out.println("from A");
} public static void main(String[] args)
{
int v = 1;
A a = new A(v) //定义了一个继承A的匿名类
{
void f(){System.out.println("from anonymous");}//覆盖父类A的方法
}; a.f();
}
}

Special Constructor
from anonymous

注意,如果在匿名类中使用了局部变量或参数,那该变量或参数必须是final。例如

public class A
{
A()
{
System.out.println("Default Constructor");
} A(int v)
{
System.out.println("Special Constructor");
} void f()
{
System.out.println("from A");
} public static void main(String[] args)
{
final int v = 1; //必须定义为final
A a = new A(v)
{
void f(){System.out.println(v);}//使用了局部变量
}; a.f();
}
}

巧记:匿名类和局部内部类一样,访问到局部参数和变量的时候都必须是final类型的。

 

2.匿名类除了继承类,还可以实现接口

public class A
{
public static void main(String[] args)
{
Thread t = new Thread //实现了Runnable接口
(
new Runnable()
{
public void run(){}
}
);
t.start();
}
}

Java逍遥游记读书笔记<二>的更多相关文章

  1. Java逍遥游记读书笔记<三>

    异常处理 如何判断一个方法中可能抛出异常 该方法中出现throw语句 该方法调用了其他已经带throws子句的方法. 如果方法中可能抛出异常,有两种处理方法: 1.若当前方法有能力处理异常,则用Try ...

  2. Java逍遥游记读书笔记<一>

    前言 必须先来一句,这是入门级别,高手勿喷~ 写Android的时候总有一些语句不是很理解,其实大部分是Java的内容,所以想系统的学下Java. 这本书——<Java逍遥游记>是在图书馆 ...

  3. java编程思想读书笔记三(11-21)

    十一:持有对象 >持有对象实例 ●数组将数字与对象联系起来.它保存类型明确的对象,查询对象时,不需要对结果做类型转换.他可以是多维的. 可以保存基本的数据类型.但是,数组一旦生成,容量就不会在变 ...

  4. 深入理解Java虚拟机之读书笔记三 内存分配策略

    一般的内存分配是指堆上的分配,但也可能经过JIT编译后被拆散为标量类型并间接地在栈上分配.对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下直接分 ...

  5. 《深入理解java虚拟机》读书笔记三——第四章

    第四章 虚拟机性能监控与故障处理工具 1.JDK命令行工具 jps命令: 作用:列出正在运行的虚拟机进程. 格式:jps [option] [hostid] 选项:-q 只输出LVMID(Local ...

  6. 《深入理解Java虚拟机》读书笔记三

    第四章 虚拟机性能监控与故障处理工具 1.JDK命令行工具 jps命令: 作用:列出正在运行的虚拟机进程. 格式:jps [option] [hostid] 选项:-q 只输出LVMID(Local ...

  7. JAVA编程思想读书笔记(三)--RTTI

    接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...

  8. JAVA编程思想读书笔记(四)--对象的克隆

    接上篇JAVA编程思想读书笔记(三)--RTTI No1: 类的克隆 public class MyObject implements Cloneable { int i; public MyObje ...

  9. 《大型网站系统与Java中间件》读书笔记 (中)

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾上一篇: <大型网站系统与Java中间件& ...

随机推荐

  1. Java 中equals和==差别

    java中的数据类型,可分为两类:  1.基本数据类型.也称原始数据类型.byte,short,char,int,long,float,double,boolean    他们之间的比較,应用双等号( ...

  2. docker中批量删除 tag为none的镜像

    添加定时任务,批量删除tag 为none 的镜像  ,释放磁盘空间 [root@weifeng]:~# crontab -l */ * * * /usr/bin/docker rmi `docker ...

  3. jumpserver v0.5.0 创建用户和管理机器

    用户管理-创建用户    data 用户详情 如下 创建用户组 data 资产列表添加资产 jumpserver 的 root 公钥需保持到 后端服务器的 authorized_keys 里, 然后测 ...

  4. sqlite 小刀 初试

    SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是嵌入式的,而且目前已经在很多嵌入式产 ...

  5. javascript常量的定义

    例如可以使用 const PI = 3.14159265; 一般不推荐使用 const 关键字,因为它不是 ECMAScript 语法的一部分.当需要常量的时候一般是以命名习惯来约束的,亦即使用大写字 ...

  6. mysql sql_mode配置

    查看mysql sql_mode SELECT @@GLOBAL.sql_mode; 修改mysql sql_mode: set global sql_mode=''; 修改my.ini: sql_m ...

  7. jsp自己主动编译机制

    总的来说,Jasper的自己主动检測实现的机制比較简单,依靠某后台线程不断检測JSP文件与编译后的class文件的最后改动时间是否同样,若同样则觉得没有改动.但倘若不同则须要又一次编译.实际上因为在T ...

  8. js 时间对比

    https://www.cnblogs.com/xiangsj/p/7977325.html http://www.jb51.net/article/45560.htm isOverdue (time ...

  9. linux Apache CGI 安装配置

    Apache 中的提交了一种利用扩展应用程序执行动态网页的机制. 称为Common Gateway Interface (通用网关接口)简称CGI. 本文假定已安装好linux(本文的linux版本为 ...

  10. atitit。html css框架Bootstrap  Foundation的比较与不同 attilax大总结

    atitit.html css框架Bootstrap  Foundation的比较与不同 attilax大总结 1. Bootstrap  Foundation的比较与不同1 2. Bootstrap ...