Abstract抽象类

1.抽象类不能被实例化

2.抽象方法没有方法体

如:

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

Sword.java

final

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

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

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

Static

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

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

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

  1. public class Test
  2. {
  3. int x;//x是一个实例变量,不能被静态方法直接访问
  4.  
  5. Test()
  6. {
  7. x = ;
  8. }
  9.  
  10. public static void main(String[] args)
  11. {
  12. System.out.println(x);
  13. }
  14. }

错误的Test.java

  1. public class Test
  2. {
  3. int x;
  4.  
  5. Test()
  6. {
  7. x = 1;
  8. }
  9.  
  10. public static void main(String[] args)
  11. {
  12. Test t1 = new Test();
  13.  
  14. System.out.println(t1.x);
  15. }
  16. }

正确的Test.java

接口

Seller.java

  1. interface Cal_Int //接口
  2. {
  3. double mul(double a, double b); //public abstract
  4. }
  5.  
  6. class Cal implements Cal_Int //实现接口的类
  7. {
  8. public double mul(double a, double b) //must public
  9. {
  10. return a*b;
  11. }
  12. }
  13.  
  14. class Seller
  15. {
  16. Cal_Int cal;
  17.  
  18. public Seller(Cal_Int cal)
  19. {
  20. this.cal = cal;
  21. }
  22.  
  23. public void compute(double price, double amount)
  24. {
  25. System.out.println(cal.mul(price, amount));
  26. }
  27.  
  28. public static void main(String[] args)
  29. {
  30. Cal_Int cal = new Cal(); //定义接口类型的引用变量,引用了实现该接口的类的实例
  31.  
  32. Seller seller = new Seller(cal);
  33.  
  34. seller.compute(0.1, 16);
  35. }
  36. }

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

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

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

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

this与super

Monkey.java

  1. public class Monkey
  2. {
  3. private String name;
  4.  
  5. private int age;
  6.  
  7. public Monkey(String name, int age)
  8. {
  9. this.name = name;
  10.  
  11. this.age = age;
  12. }
  13.  
  14. public Monkey(String name) //缺省age的时候
  15. {
  16. this(name, -1); //ok
  17.  
  18. //Monkey(name, -1); //error 不能通过类名来调用
  19. }
  20.  
  21. public Monkey(int age) //缺省name的时候
  22. {
  23. this("Anonymous", age);
  24. }
  25.  
  26. public Monkey()
  27. {
  28. this("Anonymous", -1); //缺省name和age的时候
  29. }
  30. }
  • 同一个类中,在一个构造方法中,可以通过使用this来调用另一个重载的构造方法。而不能使用类名来调用,这点很重要。
  • this语句必须放在构造方法中的第一句。

Sub.java

  1. class Base
  2. {
  3. Base(int i)
  4. {
  5. System.out.println(i);
  6. }
  7. }
  8.  
  9. public class Sub extends Base
  10. {
  11. Sub(int i)
  12. {
  13. super(i);
  14. }
  15.  
  16. Sub()
  17. {
  18. super(0);
  19. }
  20.  
  21. public static void main(String[] args)
  22. {
  23. Sub sub = new Sub();
  24.  
  25. Sub sub2 = new Sub(1);
  26. }
  27. }

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

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

内部类

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

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

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

类内:

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

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

局部内部类:

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

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

  1. class A
  2. {
  3. int a;
  4.  
  5. public void f(final int p1, int p2)
  6. {
  7. final int v1 = 2;
  8. int v2 = 1;
  9.  
  10. class B
  11. {
  12. int b1 = a; //ok
  13. int b2 = p1; //ok
  14. int b3 = p2; //error
  15. int b4 = v1; //ok
  16. int b5 = v2; //error
  17. }
  18. }
  19. }

实例内部类:

1.

  1. public class A
  2. {
  3. public class B
  4. {
  5. }
  6.  
  7. private B b = new B(); //类内直接访问B
  8. }
  9.  
  10. A.B b = new A().new B(); //类外访问要确保类名完整

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

最后一句等价于

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

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

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

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

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

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

  1. public class A
  2. {
  3. public class B
  4. {
  5. int x = 0;
  6. }
  7.  
  8. public void f()
  9. {
  10. int v1 = x; //error 万一内部类的实例没有创建呢
  11.  
  12. B b = new B();
  13.  
  14. int v2 = b.x; //ok 通过实例去访问
  15. }
  16. }

静态内部类:

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

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

  1. public class A
  2. {
  3. public static class B
  4. {
  5. int x = 0;
  6. }
  7. }
  8.  
  9. A.B b = new A.B();
  10. b.x = 2;

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

  1. public class A
  2. {
  3. int a1;
  4. static int a2;
  5.  
  6. public static class B
  7. {
  8. int b1 = a1; //error
  9.  
  10. int b2 = a2; //ok
  11.  
  12. int b3 = new A().a1; //ok
  13. }
  14. }

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

  1. public class A
  2. {
  3. public static class B
  4. {
  5. int v1;
  6.  
  7. static int v2;
  8. }
  9. }
  10.  
  11. A.Bb = new A.B();
  12. b.v1 = 1; //ok
  13. b.v2 = 2; //ok
  14. A.B.v1 = 1; //error
  15. A.B.v2 = 2; //ok

匿名类:

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

  1. public class A
  2. {
  3. A()
  4. {
  5. System.out.println("Default Constructor");
  6. }
  7.  
  8. A(int v)
  9. {
  10. System.out.println("Special Constructor");
  11. }
  12.  
  13. void f()
  14. {
  15. System.out.println("from A");
  16. }
  17.  
  18. public static void main(String[] args)
  19. {
  20. new A().f();
  21.  
  22. A a = new A() //定义了一个继承A的匿名类
  23. {
  24. void f(){System.out.println("from anonymous");}//覆盖父类A的方法
  25. };
  26.  
  27. a.f();
  28. }
  29. }

输出结果是

Default Constructor
from A
Default Constructor
from anonymous

这个语句

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

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

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

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

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

  1. public class A
  2. {
  3. A()
  4. {
  5. System.out.println("Default Constructor");
  6. }
  7.  
  8. A(int v)
  9. {
  10. System.out.println("Special Constructor");
  11. }
  12.  
  13. void f()
  14. {
  15. System.out.println("from A");
  16. }
  17.  
  18. public static void main(String[] args)
  19. {
  20. int v = 1;
  21. A a = new A(v) //定义了一个继承A的匿名类
  22. {
  23. void f(){System.out.println("from anonymous");}//覆盖父类A的方法
  24. };
  25.  
  26. a.f();
  27. }
  28. }

Special Constructor
from anonymous

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

  1. public class A
  2. {
  3. A()
  4. {
  5. System.out.println("Default Constructor");
  6. }
  7.  
  8. A(int v)
  9. {
  10. System.out.println("Special Constructor");
  11. }
  12.  
  13. void f()
  14. {
  15. System.out.println("from A");
  16. }
  17.  
  18. public static void main(String[] args)
  19. {
  20. final int v = 1; //必须定义为final
  21. A a = new A(v)
  22. {
  23. void f(){System.out.println(v);}//使用了局部变量
  24. };
  25.  
  26. a.f();
  27. }
  28. }

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

 

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

  1. public class A
  2. {
  3. public static void main(String[] args)
  4. {
  5. Thread t = new Thread //实现了Runnable接口
  6. (
  7. new Runnable()
  8. {
  9. public void run(){}
  10. }
  11. );
  12. t.start();
  13. }
  14. }

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. python——python数据结构之栈、队列的实现

    这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIF ...

  2. Win10系统Host文件修改不了权限不足怎么办

    Win10系统Host文件修改不了权限不足怎么办 Win10系统Host文件修改不了不能保存 工具原料:电脑+win10 Win10系统Host文件修改不了权限不足方法步骤如下: .打开"运 ...

  3. Redis主从配置及通过Keepalived实现Redis自动切换高可用

    Redis主从配置及通过Keepalived实现Redis自动切换高可用 [日期:2014-07-23] 来源:Linux社区  作者:fuquanjun [字体:大 中 小]   一:环境介绍: M ...

  4. 代码自动生成工具 MyGeneration

    MyGeneration 是一款不错的ORM和代码生成工具,它基于模板(Template)工作,安装好MyGeneration 后自带了很多模板,并且提供在线模板库提供模板升级和允许用户自定义模板.M ...

  5. struts2中 jsp:forward 失败原因及解决办法

    问题:在Struts2中<jsp:forward page="xxx.action"></jsp:forward>失效了,不但调转不过去还报404错误.不知 ...

  6. Struts2对于i18n的支持

    struts.xml中可以配置 <constant name="struts.custom.i18n.resources" value="itcast"& ...

  7. android http post 请求与 json字符串

    一.目标 android客户端发送一个json格式的http的请求,期望得到服务端的一个json反馈. 1. 客户端发送的json格式为: {"data" : "valu ...

  8. zookeeper(一):功能和原理

    简介 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现.分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分 ...

  9. Android 中查看内存的使用情况集经常使用adb命令

    1. 在IDE中查看Log信息 当程序执行垃圾回收的时候,会打印一条Log信息.其格式例如以下: D/dalvikvm: <GC_Reason> <Amount_freed>, ...

  10. FPGA的图像处理技术

    最近一段时间一直在研究基于FPGA的图像处理,乘着EEPW这个机会和大家交流一下,自己也顺便总结一下.主要是为了大家对用FPGA做图像处理有个感性的认识,如果真要研究的话就得更加深入学习了.本人水平有 ...