是什么?
字面意思,在类的内部编写的类就叫内部类!
为了方便区分、学习、理解我们一般将内部类分为以下几种!
内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类
有什么用?
先说个人理解,我开发经验有限,我在个人开发中很少用到内部类。一般写监听时会用(比如Android开发中的点击监听时间就应用了匿名内部类)。
即使用到了也没去了解详实的知识体系。就是没学过也会用!所以对于初学者的个人建议是了解即可,正常的面试如果问到一般就止于内部类对象的创建和数据的引用!
官方点的优点!
❀每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
❀方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
❀方便编写事件驱动程序。
❀方便编写线程代码。
在类的内部方法的外部编写的类就是成员内部类。
成员内部类特点
☄成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
☄同名属性名方法名时访问外部类 外部类.this.成员名。
MemberDemo.this.name
☄成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。所以在外部类访问内部类的时候必须先实例化外部类对象。
MemberDemo member = new MemberDemo();
Inner inner = member.new Inner();
☄成员内部类可以使用四种权限修饰符进行修饰。
☄成员内部类中不能书写静态变量和方法。
演示案例
public class MemberDemo {
String name = "王五";
static int age = 10;
public static void show() {
System.out.println("掉用外部类中的show方法");
}
public void printf() {
System.out.println("调用外部类中的打印方法");
}
//成员内部类 可以使用权限修饰符进行修饰
public class Inner{
//static double height=1.8; 成员内部类中不能使用static修饰变量和方法
String name="张三";
//成员内部类可以直接访问外部类的属性和方法
public void innerShow() {
show();
printf();
System.out.println(age);
System.out.println("我是:"+name);
System.out.println("我是:"+MemberDemo.this.name);//进行特指访问时 使用类名.this.变量名进行访问
}
}
public static void main(String[] args) {
//成员内部类对象的创建步骤
//第一步需要实例化外部类对象
//第二步正常实例化内部类对象 但是new关键字要改成 外部类对象名.new
MemberDemo member = new MemberDemo();
Inner ineer = member.new Inner();
ineer.innerShow();
}
}
编写在方法的内部的类称之为局部内部类
局部内部类的特点
☄局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
☄局部内部类不可使用权限修饰符 静态修饰符进行修饰 同局部变量相同
☄局部内部类可以直接访问方法中的属性
☄局部内部类 可以直接访问方法外部类中属性和方法
☄局部内部类 创建对象 要在方法内部 局部内部类的外部声明
演示案例
public class PartialDemo {
String name = "王五";
static int age = 10;
public static void show() {
System.out.println("掉用外部类中的show方法");
}
public void printf() {
System.out.println("调用外部类中的打印方法");
}
public void demo() {
String name = "张三";
double height = 1.8;
//编写在方法的内部的类称之为局部内部类
//局部内部类不可使用权限修饰符 静态修饰符进行修饰 同局部变量相同
//局部内部类与局部变量使用范围一样 在此方法内部
//局部内部类可以直接访问方法中的属性 重名时使用参数传递完成访问
//局部内部类 可以访问方法外部类中属性和方法
class Inner{
String name = "李四";
public void showInner(String name) {
show();
printf();
System.out.println(age);
System.out.println(height);
System.out.println("这是:"+PartialDemo.this.name);
System.out.println("这是:"+name);
System.out.println("这是:"+this.name);
}
}
//局部内部类 创建对象 要在方法内部 局部内部类的外部声明
Inner inner=new Inner();
inner.showInner(name);
}
public static void main(String[] args) {
PartialDemo partialDemo = new PartialDemo();
partialDemo.demo();
}
}
匿名内部类特点
匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
演示案例
interface A{
void show();
}
public class AnonymousDemo {
//编写回调方法 参数类型为接口A
public void calllnner(A a) {
a.show();
}
public static void main(String[] args) {
AnonymousDemo anonymousDemo = new AnonymousDemo();
//匿名内部类 监听事件使用较多
anonymousDemo.calllnner(new A() {//接口回调
//实现子类 但是没有名字 所以叫匿名内部类
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("show");
}
});
}
}
或许有些难以理解 过程其实并不复杂
首先有一个接口,然后在使用的类中编写了一个方法(参数类型是接口对象),并使用接口中未实现的方法。
我们调用此方法直接构造一个接口对象传入,此时会自动生成一个此接口的子类(匿名内部类)实现接口中的方法。本质传入的类便是此时的匿名内部类。
Android实战中的使用
modify是按钮类型的对象 传入接口或者抽象类对象 重写的方法是单机事件后的操作(不要在意干了什么) 子类没什么名字 但实际子类对象却被回调传入了setOnClickListener方法中
//修改
modify.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
db=myHelper.getWritableDatabase();//初始化数据库
values=new ContentValues();
values.put("name",nameTwo.getText().toString());
values.put("tels",numberTwo.getText().toString());
db.update("information",values,"name=?",new String[]{name});
//防止吐司出现应用程序名称提示
Toast toast=Toast.makeText(Change.this,"修改成功",Toast.LENGTH_LONG);
toast.setText("修改成功");
toast.show();
db.close();
}
});
在类中编写的以static修饰的类称为静态内部类
静态内部类特点
☄静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
☄静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法。
☄静态内部类中即能声明静态成员也可以声明非静态成员。
演示案例
public class StaticDemo {
static String name="王五";
public static class Inner{//四种权限修饰符可以修饰静态内部类
//静态内部类中不能访问外部类非静态成员
String name="张三";
static int age=18;
double height=1.8;
public void show() {
//重名时 访问外部类的静态变量使用类名.属性名访问
System.out.println("这是"+name);
System.out.println("这是"+StaticDemo.name);
System.out.println(age);
System.out.println(height);
}
}
public static void main(String[] args) {
//静态内部类可以直接实例化 不需要依附于外部类
Inner inner = new Inner();
inner.show();
}
}
成员内部类
先声明外部类对象 然后再实例化内部类对象 new关键字要改成 外部类对象名.new
局部内部类
只能在方法内部实例化对象
静态内部类
直接实例化对象
案例
实例化Bean BeanA BeanB BeanC 并打印A B C中的值
class Bean{
public void Demo() {
class BeanC{
String C = "BeanC";
}
}
}
public class InterviewDemo {
class BeanA{
String A = "BeanA";
}
static class BeanB{
String B = "BeanB";
}
}
答案(不唯一)
package com.qingsu.test;
class Bean{
public void Demo() {
class BeanC{
String C = "BeanC";
}
//实例化C
BeanC beanC = new BeanC();
System.out.println(beanC.C);
}
}
public class InterviewDemo {
class BeanA{
String A = "BeanA";
}
static class BeanB{
String B = "BeanB";
}
//实例化BeanA BeanB BeanC 对象
public static void main(String[] args) {
//实例化A
InterviewDemo interviewDemo =new InterviewDemo();
BeanA beanA = interviewDemo.new BeanA();
System.out.println(beanA.A);
//实例化B
BeanB beanB = new BeanB();
System.out.println(beanB.B);
//实例化bean
Bean bean = new Bean();
bean.Demo();
}
}
以非静态变量为例
外部类.this.属性名 可以访问到外部类属性
this.属性名 可以访问到本类属性
方法中参数传递可以访问到类外部方法中的的属性
静态内部类中对象名.属性名可以访问到外部类中的的静态属性
案例
写出控制台输出的值
public class PartialDemo {
static String name = "王五";
public void demo() {
String name = "张三";
class Inner{
String name = "李四";
public void showInner(String name) {
System.out.println("这是外部类变量:"+PartialDemo.this.name);
System.out.println("这是外部类变量(静态变量可以):"+PartialDemo.name);
System.out.println("这是方法中局部变量变量:"+name);
System.out.println("这是局部内部类中的变量:"+this.name);
}
}
Inner inner=new Inner();
inner.showInner(name);
}
public static void main(String[] args) {
PartialDemo partialDemo = new PartialDemo();
partialDemo.demo();
}
}