本帖最后由 大蓝鲸小蟀锅 于 2020-5-13 16:25 编辑
内部类的详细解释和用法
内部类 其实并不是什么地方都能用上,但是我们为什么还要学习它呢,下面我们从语法和作用上去慢慢的了解他们
语法: 类中定义类
class A{
class B{ /*
可能在刚开始学习类的时候也这样写过,当时可能是没有注意缩进格式
B就是A的内部类 编译之后会生成两个class文件 A.class A$B.class 说明内部类只是在编译期有效
到运行期 A和B是没有包含关系 是两个相互独立的类 所以内部类仅仅是一个编译期的语法
*/
}
}
分类 ---
成员内部类 和成员属性定义位置一样 可以访问外部类的私有成员,创建成员内部类必须先创建外部类对象,
语法: 外部类对象.new 内部类对象();
成员内部类中不能有静态成员
如果在内部类定义和外部类同名属性 在内部类调用的时候用 外部类.this.属性名 -->外部类.this 指向外部类的当前对象
public class 内部类 {
public static void main(String[] args) {
//我想在主方法中创建一个inner对象调用打印方法
// Outer.Inner in=new Outer.Inner();
// in.print();
/*
a是outer里边的私有属性整个属性是什么时候创建的 ?-->是在Outer创建对象的时候才有的 你现在没有创建对象呢
a是不存在的能进行打印吗,
由于成员内部类能访问外部类的私有属性,这句话潜意识的就是在说 你的先创建一个外部类对象 然后通过外部类对象
创建内部类对象
*/
Outer o1=new Outer(100);
Outer o2=new Outer(200);
Outer.Inner in = o2.new Inner(); //语法有点奇怪
in.print();
//如果我给内部定义静态属性
// 在内部类定义和外部类同名属性
//调用 System.out.println(Outer.this.a);
}
}
class Outer{
private int a=100;
public Outer(int a){
this.a=a;
}
class Inner{//这个inner就是outer类的成员内部类 它的定义位置是Outer类的成员位置上 可以用private public修饰
//里边和正常定义类一样
int a=20;
public void print(){
/*
那能不能打印a a的作用范围是整个Outer类 所以是可以打印的 inner在Outer类的封装范围内
*/
System.out.println(a);
System.out.println(Outer.this.a);
}
//static int b=10; //内部类不能有静态成员
}
}
静态内部类 和静态成员定义位置一样 静态内部类只能访问外部类的静态成员 所以不再需要先创建外部类对象
语法: new 外部类.内部类
public class 内部类 {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
inner.print();
}
}
class Outer{
private int a=10;
private static int b=20;
static class Inner{
public void print(){
System.out.println(a);//静态内部类只能访问外部类的静态成员
System.out.println(b);
}
}
}
局部内部类 使用范围等同于局部变量 局部内部类不仅可以访问外部类的私有成员 还可以访问外部类的局部变量
被内部类访问的局部变量会被拷贝一份到内部类中,即Inner中存在一个成员变量,用于记录局部变量a的值。
若局部变量不是final的,其取值就可以被修改,而Inner对象中保存的是其原来的值,这就会出现数据不同步的问题。
Java为了避免数据不同步的问题,做出了内部类只可以访问final的局部变量的限制。
在java8中,可以不使用final,如果局部变量被内部类访问,那么该局部变量相当于自动使用了final修饰。
public class 内部类 {
public static void main(String[] args) {
Outer out=new Outer();
out.method(10);
}
}
class Outer{
private int a=10;
public void method(int b){
int c=20;
class Inner{//作用范围就是method方法内部
public void print(){//我想调用这个方法怎么弄 只能抓紧在method方法内部做 出了这个方法就不能用了
System.out.println("hehe");
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
Inner in=new Inner();
in.print();
}
}
匿名内部类:
1)特殊的局部内部类
2)继承一个类或者是实现一个接口
3)只会创建该类的一个对象
4)只能用默认的构造方法
class School{
public static Teacher getTeacher(int i){
/* class CangTeacher implements Teacher{
public void Teacher(){
System.out.println("Cang teachers");
}
}
class DaTeacher implements Teacher{
public void Teacher(){
System.out.println("Da teachers");
}
}
if(i%2==0)return new CangTeacher();
else return new DaTeacher();*/
if(i%2==0)return new Teacher() {
@Override
public void Teacher() {
System.out.println("苍老师teacher");
}
} ;
else return new Teacher() {
@Override
public void Teacher() {
System.out.println("大老师讲课");
}
};
/*
无论是苍老师 还是大老师 我都只创建了一次 所以当三个条件满足之后 我就能把这个局部内部类改造成为匿名内部类
改造方式
new 接口(){
实现这个接口中的方法
}
其实我要new的不是接口 我需要的是一个对象把接口实现了 {} 这就是一个类的隐含的实现接口, 这个类叫什么不知道
匿名内部类是把 定义类,实现接口 new对象和在一起了
其实匿名内部了类的语法完全可以用局部内部类代替 匿名代码少写一行 丢掉的是程序的可读性
它的应用很广泛 很多程序员都在使用,
可以让人在编程的时候思路不断
匿名内部类能定义构造方法吗? 没名字不能
*/
}
}
interface Teacher{
public void Teacher();
}
内部类是一个编译期的语法 在运行的时候是两个独立的类 那为什么还要让一个类成为另一个类的内部类
1 内部类可以访问外部类的私有成员而不破坏封装
2 接口公开 接口的实现类作为内部类隐藏起来 强制弱耦合
public class 内部类 {
public static void main(String[] args) {
//学生写的主方法 我们这样设计希望 学生这样写代码 它和老师之间是弱耦合的 如果换个老师是对学生之间是没有影响的
//只要学校去改动getTeacher()代码
Teacher t = School.getTeacher(0);
t.Teacher();
//但是学生还可以这样写
CangTeacher c=new CangTeacher();
c.Teacher();
/*
上边也是调用苍老师的方法 下边也是调用苍老师的方法 但是如果把代码写成下面的样子我们的一番苦心就白费了
上来绕开接口和学校,直接找了苍老师 ---->这是可以的,但是我们利用接口实现弱耦合办不到了,
这事情如果是学生们都要求苍老师讲课程,学校就应该着急了,
所以为了杜绝学生这样写代码
需要从新改造
把两个老师 只能在学校的getTeacher()中使用, 所以把这两个做成局部内部类 只能学校使用,
站在学生角度只能看到 老师接口 还有学校
*/
}
}
/*class CangTeacher implements Teacher{
public void Teacher(){
System.out.println("Cang teachers");
}
}
class DaTeacher implements Teacher{
public void Teacher(){
System.out.println("Da teachers");
}
}*/
class School{ //
public static Teacher getTeacher(int i){
class CangTeacher implements Teacher{
public void Teacher(){
System.out.println("Cang teachers");
}
}
class DaTeacher implements Teacher{
public void Teacher(){
System.out.println("Da teachers");
}
}
if(i%2==0)return new CangTeacher();
else return new DaTeacher();
}
}
interface Teacher{
public void Teacher();
}
|
|