天猫官方网站,wordpress轮播的插件,云南建设招标网站首页,广州市白云区建设局 网站内部类 Inner Class 一个内部类可以定义在另一个类里#xff0c;可以定义在函数里#xff0c;甚至可以作为一个表达式的一部分。 Java中的内部类共分为四种#xff1a; 静态内部类static inner class (also called nested class) 成员内部类member inner class 局部内部类l…内部类 Inner Class 一个内部类可以定义在另一个类里可以定义在函数里甚至可以作为一个表达式的一部分。 Java中的内部类共分为四种 静态内部类static inner class (also called nested class) 成员内部类member inner class 局部内部类local inner class 匿名内部类anonymous inner class 1 成员内部类 member inner class 1.1 形式 成员内部类也是定义在另一个类中但是定义时不用static修饰。形如 1 class Outer {
2 class Inner{
3
4 }
5 } 编译之后会产生如下2个class文件: ----这可以将相关的类组织在一起从而降低了命名空间的混乱。 成员内部类的修饰符对于普通的类可用的修饰符有final、abstract、strictfp、public和默认的包访问。但是成员内部类更像一个成员变量和方法。可用的修饰符有final、abstract、public、private、protected、strictfp和static。一旦用static修饰内部类它就变成静态内部类了。 1.2 创建内部类实例 成员内部类就像一个实例变量他依赖于外部类的实例存在 -- 必须先有外部类的实例 才能创建成员内部类对象 在外部类里面创建成员内部类的实例this.new Innerclass(); 或可以用 Inner inner new Inner(); 方法直接创建 在外部类之外创建内部类的实例(new Outerclass()).new Innerclass(); 或 Inner inner new Outer().new Inner() 或 Outer outer new Outer(); Inner inner outer.new Inner(); 案例从外部类的非静态方法中实例化内部类对象。 1 class Outer {2 private int i 10;3 public void makeInner(){4 Inner in new Inner();5 in.seeOuter();6 }7 class Inner{8 public void seeOuter(){9 System.out.print(i);
10 }
11 }
12 } 表面上我们并没有创建外部类的对象就实例化了内部类对象和上面的话矛盾。事实上如果不创建外部类对象也就不可能调用makeInner()方法所以到头来还是要创建外部类对象的。你可能试图把makeInner()方法修饰为静态方法即static public void makeInner()。这样不创建外部类就可以实例化外部类了但是在一个静态方法里能访问非静态成员和方法吗显然不能。 -- 必须先有外部类的实例 才能创建成员内部类对象 案例从外部类的静态方法中实例化内部类对象 1 class Outer {2 private int i 10;3 class Inner{4 public void seeOuter(){5 System.out.print(i);6 }7 } 8 public static void main(String[] args) {9 Outer out new Outer();
10 Outer.Inner in out.new Inner();
11 //Outer.Inner in new Outer().new Inner();
12 in.seeOuter();
13 }
14 } 被注释掉的那行是它上面两行的合并形式一条简洁的语句。对比一下在外部类的非静态方法中实例化内部类对象是普通的new方式Inner in new Inner();在外部类的静态方法中实例化内部类对象必须先创建外部类对象Outer.Inner in new Outer().new Inner(); 1.3 成员内部类操作外部类 成员内部类可以访问它的外部类的所有成员变量和方法不管是静态的还是非静态的都可以。 内部类就像一个实例成员一样存在于外部类所以内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制。 内部类中的this指的是内部类的实例对象本身如果要用外部类的实例对象就可以用类名.this的方式获得。 普通的类可以用this引用当前的对象内部类也是如此。 但是假若内部类想引用外部类当前的对象呢用“外部类名”.this的形式,如下例的Outer.this。 1 class Outer {2 class Inner{3 public void seeOuter(){4 System.out.println(this);5 System.out.println(Outer.this);6 }7 }8 9 public static void main(String[] strs){
10 new Outer().new Inner().seeOuter();
11 }
12 }
13
14 输出
15 Outer$Inner61de33
16 Outer14318bb 1.4 内部类对象中不能有静态成员 原因很简单内部类的实例对象是外部类实例对象的一个成员若没有外部类对象内部类就不会存在何谈静态成员呢。 1 class Outer {2 class Inner{3 static int i 0;4 public void seeOuter(){5 System.out.println(this);6 System.out.println(Outer.this);7 }8 }9
10 public static void main(String[] strs){
11 new Outer().new Inner().seeOuter();
12 }
13 } 我们编译这个类 1 E:\javac Outer.java
2 Outer.java:3: 内部类不能有静态声明
3 static int i 0;
4 ^
5 1 错误 2 局部内部类local inner class 局部内部类local inner class 也可以成为方法内部类 顾名思义就是把类放在方法内。局部内部类定义在方法中比方法的范围还小。是内部类中最少用到的一种类型。 像局部变量一样不能被public, protected, private和static修饰。 局部内部类在方法中定义所以只能在方法中使用即只能在方法当中生成局部内部类的实例并且调用其方法。 1 class Outer {2 public void doSomething(){3 class Inner{4 public void seeOuter(){5 System.out.println(inner class);6 }7 } 8 9 Inner inner new Inner();
10 inner.seeOuter();
11 }
12
13 public static void main(String ... args){
14 new Outer().doSomething();
15 }
16 } 输出 inner class 局部内部类只能在声明的方法内是可见的因此定义局部内部类之后想用的话就要在方法内直接实例化记住这里顺序不能反了一定是要先声明后使用否则编译器会说找不到。 方法内部类的修饰符 与成员内部类不同方法内部类更像一个局部变量。 可以用于修饰方法内部类的只有final和abstract。 注意事项A: 方法内部类只能在定义该内部类的方法内实例化不可以在此方法外对其实例化B: 方法内部类对象不能使用该内部类所在方法的非final局部变量。原因 因为方法的局部变量位于栈上只存在于该方法的生命期内。当一个方法结束其栈结构被删除局部变量成为历史。 但是该方法结束之后在方法内创建的内部类对象可能仍然存在于堆中例如如果对它的引用被传递到其他某些代码并存储在一个成员变量内。 正因为不能保证局部变量的存活期和方法内部类对象的一样长所以内部类对象不能使用它们。下面是完整的例子 1 class Outer {2 public void doSomething(){3 final int a 10;4 class Inner{5 public void seeOuter(){6 System.out.println(a);7 }8 } 9 Inner in new Inner();
10 in.seeOuter();
11 }
12 public static void main(String[] args) {
13 Outer out new Outer();
14 out.doSomething();
15 }
16 } C:静态方法内的方法内部类。 静态方法是没有this引用的因此在静态方法内的内部类遭受同样的待遇即只能访问外部类的静态成员。 3 匿名内部类Anonymous Inner Class 顾名思义没有名字的内部类。 匿名内部类就是没有名字的局部内部类不使用关键字class, extends, implements, 没有构造方法。 匿名内部类隐式地继承了一个父类或者实现了一个接口。 匿名内部类使用得比较多通常是作为一个方法参数。 A、继承式的匿名内部类。 1 class Car {2 public void drive(){3 System.out.println(Driving a car!);4 }5 }6 7 8 class Test{9 public static void main(String[] args) {
10 Car car new Car(){
11 public void drive(){
12 System.out.println(Driving another car!);
13 }
14 };
15 car.drive();
16 }
17 } 结果输出了Driving another car! 建立匿名内部类的关键点是重写父类的一个或多个方法。再强调一下是重写父类的方法而不是创建新的方法。因为用父类的引用不可能调用父类本身没有的方法创建新的方法是多余的。简言之参考多态。 B、接口式的匿名内部类。 1 interface Vehicle {2 public void drive();3 }4 5 6 class Test{7 public static void main(String[] args) {8 Vehicle v new Vehicle(){9 public void drive(){
10 System.out.println(Driving a car!);
11 }
12 };
13 v.drive();
14 } 这种形式的代码我们一定写过这也是内部类的存在的一个重要作用便于编写 线程和事件驱动的代码 1 public class ThreadDemo {2 public static void main(String[] args) {3 4 new Thread(new Runnable(){5 public void run(){6 System.out.println(Hello World!);7 }8 }).start();9 }
10 }
11
12
13 E:\javac ThreadDemo.java
14 E:\java ThreadDemo
15 Hello World! 1 public class SwingTest2 {3 public static void main(String[] args)4 {5 JFrame frame new JFrame(JFrame);6 JButton button new JButton(JButton);7 8 button.addActionListener(new ActionListener(){9
10 Override
11 public void actionPerformed(ActionEvent arg0){
12 System.out.println(Hello World);
13
14 }
15 });
16
17 frame.getContentPane().add(button);
18 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
19 frame.setSize(200, 200);
20
21 frame.addWindowListener(new WindowAdapter() {
22
23 Override
24 public void windowClosing(WindowEvent e){
25 System.out.println(Closing);
26 System.exit(0);
27 }
28 });
29
30 frame.setVisible(true);
31 }
32 } 若你了解安卓的话 会发现这样的代码编写方式有着很多的应用 好处就是简化我们的代码。 C、参数式的匿名内部类。 1 class Bar{2 void doStuff(Foo f){}3 }4 5 inteface Foo{6 void foo();7 }8 9 class Test{
10 static void go(){
11 Bar b new Bar();
12 b.doStuff(new Foo(){
13 public void foo(){
14 System.out.println(foofy);
15 }
16 });
17 }
18 }
19 4 静态内部类static inner class 在定义成员内部类的时候可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。 同样会被编译成一个完全独立的.class文件名称为OuterClass$InnerClass.class的形式。 只可以访问外部类的静态成员和静态方法包括了私有的静态成员和方法。 生成静态内部类对象的方式为OuterClass.InnerClass inner new OuterClass.InnerClass(); 静态内部类使用代码 1 package com.learnjava.innerclass;2 3 class StaticInner4 {5 private static int a 4;6 7 // 静态内部类8 public static class Inner9 {
10 public void test()
11 {
12 // 静态内部类可以访问外部类的静态成员
13 // 并且它只能访问静态的
14 System.out.println(a);
15 }
16
17 }
18 }
19
20 public class StaticInnerClassTest
21 {
22
23 public static void main(String[] args)
24 {
25 StaticInner.Inner inner new StaticInner.Inner();
26 inner.test();
27 }
28 } 与一般内部类不同在静态代码中不能够使用this操作所以在静态内部类中只可以访问外部类的静态变量和静态方法。使用静态内部类的目的和使用内部类相同。如果一个内部类不依赖于其外部类的实例变量或与实例变量无关则选择应用静态内部类。 可以在静态内部类的方法中直接访问外部类的静态变量和调用静态方法。但不允许访问外部类的实例变量以及实例方法。静态内部类的实例方法中亦只允许访问外部类的静态成员。 静态内部类不同于其他3种内部类他有着自己特殊的特性参看解析静态内部类的使用目的与限制 5 小结 5.1 几种内部类的共性 A、内部类仍然是一个独立的类在编译之后会内部类会被编译成独立的.class文件但是前面冠以外部类的类命和$符号。B、内部类不能用普通的方式访问。内部类是外部类的一个成员因此内部类可以自由地访问外部类的成员变量无论是否是private的。 5.2 java中为什么要引入内部类还有匿名内部类? 1)可以是单继承的一种补充解决方案 inner classes能有效实际地允许“多重实现继承multiple implementation” Java中一个类只能继承一个类 可以通过内部类达到继承多个类的效果 每个inner class都能够各自继承某一实现类implementation因此inner class不受限于outer class是否已继承自某一实现类。 2)针对具体的问题提供具体的解决方案同时又能对外隐藏实现细节 看具体的案例 案例1 在集合中可以使用Iterator遍历 但每一种集合的数据结构不同 导致遍历的方法必然也不同 所以Java在每个具体的集合里定义了一个内部类Itr 他实现了Iterator接口 从而根据所在类的具体情况进行遍历 1 public interface Iterator {//迭代器的功能2 boolean hasNext();3 Object next(); 4 }5 6 public interface Iterable {//返回迭代器的能力7 Iterator iterator();8 }9
10 public interface Collection extends Iterable {
11 Iterator iterator();
12 }
13
14 public interface List extends Collection {
15 Iterator iterator();
16 }
17
18 public class ArrayList implements List {
19 public Iterator iterator() {
20 return new Itr();
21 }
22
23 private class Itr implements Iterator {
24 //每种集合的具体实现采用了不同的数据结构
25 public boolean hasNext() {......}
26 public Object next(){......}
27 }
28 }
29
30 Collection c new ArrayList();
31 c.add(hello);
32 c.add(world);
33 c.add(java);
34 Iterator it c.iterator(); //new Itr();
35 while(it.hasNext()) {
36 String s (String)it.next();
37 System.out.println(s);
38 } Itr是private的类 对外并不可见 因为我的遍历方法我自己知道就可以了 别人并不需要了解 集合类有实现了Tterable接口 通过里面的iterator方法获取该内部类实例 外部不能直接创建该内部类的实例 案例2 为某个类提供特定的数据结构 为了共同解决一个具体的问题 但又可以对外部保持透明 如HashMap中有Entry ConcurrentHashMap有HashEntry 和Segment 看HashMap中的内部类 1 public class HashMapK,V2 extends AbstractMapK,V3 implements MapK,V, Cloneable, Serializable4 {5 6 static final Entry?,?[] EMPTY_TABLE {};7 transient EntryK,V[] table (EntryK,V[]) EMPTY_TABLE;8 9 static class EntryK,V implements Map.EntryK,V {
10 final K key;
11 V value;
12 EntryK,V next;
13 int hash;
14 // ... ...
15 }
16 } 关于HashMap 可以参考HashMap源码解析 关于ConcurrentHashMapConcurrentHashMap ConcurrentHashMap原理分析转载于:https://www.cnblogs.com/wihainan/p/4773090.html