一.内部类

1.1 什么是内部类

定义在类里面的类,就是一个内部类。

1.2 内部类分类

内部类4种形态
成员内部类 静态内部类 方法内部类( 局部内部类 ) 匿名内部类

二.成员内部类

2.1 理解

成员内部类,和实例属性 实例方法 动态代码块 构造器 是同一级别的事物,实例级别内容。

2.2 定义

  1. //外部类
  2. public class Foo {
  3. //内部类:成员内部类
  4. class Boo{
  5. }
  6. }

2.3 成员内部类成分

  1. //外部类
  2. public class Foo {
  3. //内部类:成员内部类
  4. class Boo{
  5. int age; // OK 实例属性
  6. static int name; //ERROR 不能定义静态属性
  7. // OK 普通代码块
  8. {
  9. }
  10. // ERROR 不可以定义
  11. static {
  12. }
  13. //OK 构造器
  14. public Boo(){
  15. }
  16. //OK 实例方法
  17. public void m1(){
  18. }
  19. // ERROR 报错不可定义静态方法
  20. public static void m2(){
  21. }
  22. }
  23. }

不可以定义 static 相关内容,除此都可以。

2.4 成员访问规则

2.4.1 内部类访问外部

可以访问 实例信息和静态信息(全部),如果内部类访问外部类的同名属性默认,就近原则,通过 外部类名.this.xxx 可以强制区分外部类属性。

  1. //外部类
  2. public class Foo {
  3. int fmoney;
  4. static int fheight;
  5. public void f1(){
  6. }
  7. public static void f2(){
  8. }
  9. //内部类:成员内部类
  10. class Boo{
  11. int age; //实例属性
  12. public void m1(){ //实例方法
  13. System.out.println( fmoney ); //OK 可直接访问
  14. System.out.println( fheight); //OK 可直接访问
  15. f1(); //OK 可直接访问
  16. f2(); //OK 可直接访问
  17. }
  18. }
  19. }

2.4.2 外部类访问内部

  1. //外部类
  2. public class Foo {
  3. int fmoney;
  4. static int fheight;
  5. public void f1(){
  6. Boo boo = new Boo(); // 1 创建对象
  7. boo.m1(); // 2 对象来访问即可
  8. }
  9. public static void f2(){
  10. }
  11. //内部类:成员内部类
  12. class Boo{
  13. int age; //实例属性
  14. public void m1(){ //实例方法
  15. }
  16. }
  17. }

2.4.3 其他位置访问内部类

需要创建对象然后使用

  1. public static void main(String[] args) {
  2. //分开来写
  3. Foo foo = new Foo();
  4. Foo.Boo boo1= foo.new Boo();
  5. //一步到位
  6. Foo.Boo boo2 = new Foo().new Boo();
  7. boo2.xx();
  8. }

通过对象引用调用属性和方法。
内部类单独使用,声明类型的时候需要带外部类名一起声明。比如 Foo.Boo

2.5 成员内部类使用案例


/

  1. package case2;
  2. public class Car {
  3. //名字
  4. String brand;
  5. public Car(String brand){
  6. this.brand=brand;
  7. }
  8. //汽车行驶方法 需要发动机提供动力
  9. public void run(){
  10. System.out.println(brand+"启动");
  11. Engine engine = new Engine();
  12. engine.zhuan();
  13. }
  14. //引擎,对外不公开,专门为外部类设计,为外部类提供服务
  15. private class Engine {
  16. public void zhuan(){
  17. System.out.println("发动机运行");
  18. }
  19. }
  20. }
  21. package case2;
  22. // 内部类使用案例
  23. public class TestCar {
  24. public static void main(String[] args) {
  25. Car car = new Car("宝马");
  26. car.run();
  27. }
  28. }

三.静态内部类

3.1 理解

静态内部类,和静态属性 静态方法 静态代码块 是同一级别的事物,是类级别内容。

3.2 定义

  1. public class Foo {
  2. //静态内部类
  3. static class Boo{
  4. }
  5. }

3.3 定义成分

  1. public class Foo {
  2. static class Boo{
  3. int age ; // 实例属性 OK
  4. static int money; // 静态方法 OK
  5. // 构造器 OK
  6. public Boo(){
  7. }
  8. // 实例方法 OK
  9. public void m1(){}
  10. // 静态方法 OK
  11. public static void m2(){}
  12. // 普通代码块OK
  13. {
  14. }
  15. // 静态代码块 OK
  16. static {
  17. }
  18. }
  19. }

从定义成分上看,几乎等价与一个普通外部类

3.4 成员访问规则

3.4.1 内部类访问外部类

只能访问到静态内容(静态属性 静态方法)

3.4.2 外部类访问内部类

就是一个普通类的访问方式:
通过类名访问静态属性和方法
通过对象访问实例属性和方法

3.4.3其他位置访问内部类

就是一个普通类的访问方式:
通过类名访问静态属性和方法
通过对象访问实例属性和方法

四.方法内部类

4.1 理解

方法内部类,定义外部类的方法中,和方法的局部变量同级别。

4.2 定义

  1. public class Foo {
  2. public void f1(){
  3. int age = 10;
  4. //方法内部类
  5. class Boo{
  6. }
  7. }
  8. }

4.3 定义成分

  1. public void f1(){
  2. int age = 10;
  3. // 内部类
  4. class Boo{
  5. //实例属性 OK
  6. int age;
  7. // 构造器 OK
  8. public Boo(){
  9. }
  10. // 动态代码块 OK
  11. {
  12. }
  13. public void m1(){ // 实例方法 OK
  14. }
  15. }
  16. }

只能定义实例相关信息,不可定义静态内容,且不可添加访问权限。

4.4 成员访问规则

4.4.1 内部类访问外部类

可以直接访问静态和实例的信息。

4.4.2 外部类访问内部类

就是一个普通类的访问方式:
通过对象访问实例属性和方法 ,只能在内部类所在方法中使用

4.4.3 细节面试题

局部内部类访问 所在方法的 局部变量,要求这个变量是final修饰的,在JDK7必须强制声明为final,JDK8中无需声明,但是编译器依然要求它是一个final。

为什么呢? 需要延长局部变量的生命周期,保证对象使用该变量时,它是存在的,通过final 修饰的变量进入常量池,会一直保存。

五.匿名内部类

5.1 理解

没有名字的内部类,是一种特殊的局部内部类。它是把类的定义和对象创建合二为一。匿名内部类只能创建一次对象。匿名内部类必须是某个接口的实现类或者是某个类的子类。

5.2 定义

  1. //接口
  2. public interface CanFly {
  3. public void fly();
  4. }
  5. public static void main(String[] args) {
  6. CanFly xx = new CanFly(){
  7. @Override
  8. public void fly() {
  9. System.out.println("小鸟飞");
  10. }
  11. };
  12. }

5.3 编程中的运用

  1. //创建面板时添加一个按钮
  2. public Scene(){
  3. //不要使用布局管理器,用坐标布局
  4. this.setLayout(null);
  5. JButton btn = new JButton("点我呀"); //创建一各按钮对象
  6. btn.setBounds(0,0,100,30);//设置按钮位置
  7. this.add(btn); //添加到面板
  8. //添加一个点击监听
  9. btn.addActionListener(new ActionListener() { //这里使用匿名内部类
  10. @Override
  11. public void actionPerformed(ActionEvent e) {
  12. System.out.println("你好呀");
  13. }
  14. });
  15. }

GUI 编程, 体会面向对象编程
GUI 编程它是 图形化界面编程,目前的编程是控制台程序。
GUI java 的图形化编程是否流行 ?不流行,现在学习java 一般不学,但是可以做一些了解。它就是JAVA官方基于面向对象构建的一套编程技术。我们可以通过他们消化和理解面向对象的编程技术。

  1. package case4.gui;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.*;
  5. //程序入口
  6. public class App {
  7. public static void main(String[] args) {
  8. //创建一个窗体对象
  9. JFrame win = new JFrame();
  10. //设置 标题
  11. win.setTitle("千锋App");
  12. //设置 尺寸
  13. win.setSize(1000,600);
  14. //添加一个面板
  15. //JPanel pan = new JPanel();
  16. //设置面板的颜色
  17. //pan.setBackground( Color.ORANGE ); // java 万物皆为对象 颜色也是对象 Color类表示颜色类
  18. JPanel pan = new JPanelPlus();
  19. win.add( pan );
  20. //设置 可见性
  21. win.setVisible( true );
  22. //设置 关闭操作
  23. win.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
  24. //事件处理 MouseAdapter 的匿名内部类
  25. win.addMouseListener(
  26. new MouseAdapter() {
  27. @Override
  28. public void mouseClicked(MouseEvent e) {
  29. System.out.println("helllo:"+e.getX()+"---"+e.getY());
  30. }
  31. }
  32. );
  33. // 键盘事件
  34. win.addKeyListener(new KeyAdapter() {
  35. @Override
  36. public void keyPressed(KeyEvent e) { // KeyEvent e事件对象 保存事件信息
  37. switch (e.getKeyCode()){
  38. case KeyEvent.VK_W:
  39. System.out.println("上");break;
  40. case KeyEvent.VK_S:
  41. System.out.println("下");break;
  42. case KeyEvent.VK_A:
  43. System.out.println("左");break;
  44. case KeyEvent.VK_D:
  45. System.out.println("右");break;
  46. default:
  47. System.out.println("输入错误");
  48. }
  49. }
  50. });
  51. }
  52. }
  53. package case4.gui;
  54. import javax.swing.*;
  55. import java.awt.*;
  56. //自定义面板
  57. public class JPanelPlus extends JPanel {
  58. //JPpanel 不画任何东西,我们需要画东西,不得已来重写一盘。
  59. @Override
  60. public void paint(Graphics g) {
  61. super.paint(g);
  62. //画东西需要画笔 Graphics g 功能少
  63. Graphics2D g2D = (Graphics2D) g;
  64. g2D.setStroke( new BasicStroke(15) ); //设置画笔大小
  65. //设置抗锯齿
  66. g2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING,
  67. RenderingHints.VALUE_ANTIALIAS_ON );
  68. g.setColor(Color.blue);
  69. g.drawOval(220,220,200,200);
  70. g.setColor(Color.darkGray);
  71. g.drawOval(440,220,200,200);
  72. g.setColor( Color.pink );
  73. g.drawOval(100,100,200,200);
  74. g.setColor(Color.orange);
  75. g.drawOval(320,100,200,200);
  76. g.setColor(Color.green);
  77. g.drawOval(540,100,200,200);
  78. }
  79. }