内部类:定义在类结构中的另一个类:
类中的定义的成员:字段、方法、内部类
为什么使用内部类?
- 增强封装,把内部类隐藏在外部类之内,不许其他类访问该类。
- 内部类能提高代码的可读性和可维护性,把小型类嵌入到外部类中结构上代码更靠近。
- 内部类可以直接访问外部类的成员。
package com.test;
//双向链表
public class LinkledList {
//第一个节点
private Node first;
//最后一个节点
private Node last;
//火车的车厢是在火车的内部
class Node{
private Node prev;//上一个节点
private Node next;//下一个节点
private Object ele;//当前节点存储的数据
}
}
外部类的访问修饰符:要么public要么缺省。
内部类看做是外部类的一个成员,那么内部类可以使用public/缺省\protected\private修饰,还可以是static修饰。
内部类分为四种:
- 实例内部类:内部类没有使用static修饰
- 静态内部类:内部类使用了static修饰
- 局部内部类:在方法中定义的内部类
- 匿名内部类适合于使用一次使用的类,属于局部内部类的特殊情况。
对于每个内部类来说:java编译器会生成独立的.class文件。 - 成员内部类:外部类$内部类名称
- 局部内部类:外部类名$数字&内部类名称
- 匿名内部类:外部类名¥数字
实例内部类:没有static修饰内部类,说明内部类属于外部类的对象
特点:
- 创建实例内部类前,必须存在外部类对象,通过外部类对象创建内部类对象(当存在内部类对象时,一定存在外部类对象)。
package com.test;
class Outer{
String name="ok";
class Inner{
void print(){
System.out.println(name);
}
}
}
public class test1{
public static void main(String[] args){
Outer out=new Outer();
out.new Inner().print();;//通过外部类对uter.Inner in=out.new Inner();
}
}
- 实例内部类的实例自动持有外部类的实例的引用,内部类可以直接访问外部类成员。
- 外部类中不能够直接访问内部类的成员,必须通过内部类的实例去访问。
class Outer{
String name="外部类";
void OuterPrint(){
System.out.println(new Inner().str);
}
class Inner{
private String str="内部类";
void print(){
System.out.println(name);
}
}
}
“` - 如果实例内部类和外部类存在同名的字段和方法abc,在内部类中:this.abc:表示
访问内部类成员,反之亦然。
静态内部类:
使用static修饰的内部类。
特点:
- 静态内部类的实例不会自动持有外部类的特定实例的引用,在创建内部类的实例时,不必创建外部类的实例。
package com.test;
class Outer{
static String name="外部类";
static class Inner{
private static final String str="内部类";
void print(){
System.out.println(name);
}
}
}
public class test1{
public static void main(String[] args){
//不必new Outer().new Inner(),因此不必创建外部类的实例
new Outer.Inner().print();
}
}
2.静态内部类中可以直接访问外部类的静态成员,如果访问外部类的实例成员,必须通过外部类的实例去访问。
class Outer{
static String str="外部类";
String s="非静态";
static class Inner{
static void print(){
System.out.println(str);
}
}
}
3.在静态内部类中可以定义静态成员和实例成员。
4.测试类可以通过完整的类名直接访问静态内部类的静态方法。
package com.test;
class Outer{
static class Inner{
static void print(){
System.out.println("静态内部类");
}
}
}
public class test1{
public static void main(String[] args){
//不必new Outer().new Inner(),因此不必创建外部类的实例
Outer.Inner.print();
}
}
局部内部类(没啥用):
在方法中的定义的内部类,其可见范围是当前方法和局部变量是同一个级别。
public class test1{
public static void main(String[] args){
class Inner{
void print(){
System.out.println("内部类");
}
}
}
}
1.不能使用public、private、protected和static修饰符。
2.局部内部类只能在当前方法中使用。
3.局部内部类和实力内部类一样,不能包含静态成员。
4.局部内部类和实力内部类,可以访问外部类的所有成员。
5.
局部内部类访问的局部变量必须使用final修饰(在java中自动隐式加上final,但是依然是常量不能改变值)。
![]()
上述代码报错!!!
package com.test;
public class test1{
public static void main(String[] args){
final int num=17;
class Inner{
void print(){
System.out.println(num);
}
}
new Inner().print();
}
}
java 中变量存储位置的区别
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(public static final)。
6. 非RAM存储:硬盘等永久存储空间
如果用final修饰变量就是常量存放在常量池中,当方法被销毁后对象仍然可以调用。
匿名内部类:是一个没有名称的局部内部类,适合只使用依次的类,是特殊的局部内部类,满足局部内部类特征。