Java笔记:内部类
1.把一个类放在另一类内部定义,这个定义在其他类里面的类就叫做内部类,包含内部类的类叫做外部类。内部类成员可以直接访问外部类的私有数据,但是外部类不能访问内部类的实现细节。
2.非静态内部类(没有static修饰的内部类)
package cn.lsl;
public class Cow {
private double weight;
public Cow(){}
public Cow(double weight){
this.weight = weight;
}
private class CowLeg{
private double length;
private String color;
public CowLeg(double length, String color) {
super();
this.length = length;
this.color = color;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void info(){
System.out.println("颜色:" + color + ",高:" + length);
System.out.println("重:" + weight);
}
}
public void test(){
CowLeg cl = new CowLeg(2, "红色");
cl.info();
}
public static void main(String[] args) {
Cow cow = new Cow(123);
cow.test();
}
}
System.out.println("重:" + weight);这句代码在非静态内部类里可以直接访问外部类的private成员。
当调用非静态内部类的实例方法时,必须有一个静态内部类实例,而非静态内部类实例必须寄存在外部类实例里。
3.如果在外部类、内部类、内部类里方法里面出现了同名的变量,则可以通过this、外部类类名.this来访问
package cn.lsl;
public class Variable {
private String a = "外部类实例变量";
private class In{
private String a = "内部类实例变量";
public void info(){
String a = "局部变量";
System.out.println("外部类:" + Variable.this.a);
System.out.println("内部类:" + this.a);
System.out.println("局部变量:" + a);
}
}
public void test(){
In in = new In();
in.info();
}
public static void main(String[] args) {
new Variable().test();
}
}
三种访问形式:
System.out.println("外部类:" + Variable.this.a);
System.out.println("内部类:" + this.a);
System.out.println("局部变量:" + a);
4.外部类不能直接访问非静态内部类的实例Field,如果外部类需要访问非静态内部类的成员,则必须显示创建非静态内部类对象来调用访问其实例成员。
package cn.lsl;
public class Outer {
private int a = 5;
class In{
private int b = 23;
public void accessOuter(){
System.out.println("直接访问外部类的a的值" + a);
}
}
public void accessIn(){
//System.out.println("内部类b的值:" + b); 编译出错,不能直接访问
System.out.println("内部类b的值:" + new In().b);
}
public static void main(String[] args) {
Outer out = new Outer();
out.accessIn();
}
}
非静态内部类对象必须寄存在外部类对象里面,而外部类对象不一定要有非静态内部类对象寄存其中。即,如果存在一个非静态内部类对象,一定要存在一个被它寄存的外部类对象。
5.静态内部类(使用static修饰的内部类)
(1)如果使用static修饰一个内部类,则这个内部类就属于外部类本身,不属于外部类的某个对象。
(2)静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。
package cn.lsl;
public class StaticIn{
private int a = 5;
private static int b = 23;
static class In{
private static int age;
public void accessOut(){
//System.out.println(a); //编译出错
System.out.println(b);
}
}
}
(3)外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员
package cn.lsl;
public class StaticIn{
static class In{
private static int a = 5;
private int b = 23;
}
public void accessIn(){
// System.out.println(a); //编译出错
System.out.println(In.a);
// System.out.println(b); //编译出错
System.out.println(new In().b);
}
}
6.在外部类以外使用非静态内部类
如果希望在外部类以外的地方访问内部类,则内部类不能使用private访问控制权限,private修饰的内部类只能在外部类内部使用。
非静态内部类的对象必须寄存在外部类的对象里,因此创建非静态内部类之前,必须先创建其外部类对象。
eg:
package cn.lsl; class Out {
class In{
public In(String msg){
System.out.println(msg);
}
}
} public class CreateIn{
public static void main(String[] args) {
Out.In in = new Out().new In("测试信息");
}
}
在外部类以外的地方创建非静态内部类实例必须使用外部类实例和new来调用非静态内部类的构造器。
7.在外部类以外使用静态内部类
因为静态内部类是外部类类相关的,因此创建内部类对象时无须创建外部类对象。
package cn.lsl;
class StaticOut{
static class In{
public In(){
System.out.println("静态内部类的构造器");
}
}
}
public class CreateStaticOut {
public static void main(String[] args) {
StaticOut.In in = new StaticOut.In();
}
}
静态内部类和非静态内部类声明变量的语法是一样的,区别在于创建内部类对象时,静态内部类只需使用外部类即可调用构造器,而非静态内部类必须使用外部类对象来调用构造器。
8.局部内部类
如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。
由于局部内部类不能再方法以外的地方使用,因此局部内部类也不能使用访问控制符和static修饰符修饰。
如果需要用局部内部类定义变量,创建实例或派生子类,那么都只能在局部内部类所在的方法内进行。
package cn.lsl;
public class LocalIn {
public static void main(String[] args) {
class InnerBase{
int a;
}
class InnerSub extends InnerBase{
int b;
}
InnerSub is = new InnerSub();
is.a = 5;
is.b = 8;
System.out.println(is.a + "," + is.b);
}
}
9.匿名内部类
(1)匿名内部类适合创建那种只需要一次使用的类,创建匿名内部类时会立即创建一个该类的实例,这个类定义即消失,匿名内部类不能重复使用。
(2)匿名内部类的格式
new 父类构造器(实参列表)|实现接口(){
}
(3)匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
(4)匿名内部类不能是抽象类。
(5)匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器。但匿名内部类可以定义实例初始化块,通过实例初始化块来完成构造器需要完成的事情。
package cn.it.lsl;
interface Product{
public double getPrice();
public String getName();
}
public class AnonymousTest{
public void test(Product p){
System.out.println("购买" + p.getName() + ",花掉了" + p.getPrice());
}
public static void main(String[] args) {
AnonymousTest ta = new AnonymousTest();
ta.test(new Product(){
@Override
public double getPrice() {
// TODO Auto-generated method stub
return 190;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return "声卡";
}
});
}
}
test()方法需要传入一个Product对象作为参数,但Product只是一个接口,因此此处考虑创建一个Product接口实现类的对象传入该方法。
上面匿名内部类部分也可以等价于下面这段代码
public class AnonymousTest implements Product{
@Override
public double getPrice() {
// TODO Auto-generated method stub
return 100;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return "声卡";
}
public void test(Product p){
System.out.println("购买" + p.getName() + ",花掉了" + p.getPrice());
}
public static void main(String[] args) {
AnonymousTest ta = new AnonymousTest();
ta.test(new AnonymousTest());
}
}
10.如果通过继承父类来创建匿名内部类,匿名内部类将拥有和父类相似的构造器,此处的相似指的是拥有相同的形参列表。
package cn.it.lsl;
abstract class Device{
private String name;
public abstract double getPrice();
public Device(){}
public Device(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class AnonymousInner {
public void test(Device d){
System.out.println("购买一个" + d.getName() + ",花掉了" + d.getPrice());
} public static void main(String[] args) {
AnonymousInner ai = new AnonymousInner();
ai.test(new Device("鼠标"){ @Override
public double getPrice() {
// TODO Auto-generated method stub
return 23;
}
});
Device d = new Device() {
{
System.out.println("匿名内部类初始化块");
} @Override
public double getPrice() {
// TODO Auto-generated method stub
return 32;
} //重写父类的实例方法
public String getName(){
return "键盘";
}
};
ai.test(d);
}
}
当创建匿名内部类时,必须实现接口或抽象父类里的所有抽象方法。如果有需要,也可以重写父类中的普通方法。
11.如果匿名内部类需要访问外部类的局部变量,则必须使用final修饰符来修饰外部类的局部变量
package cn.it.lsl;
interface A{
void test();
}
public class ATest {
public static void main(String[] args) {
//int age = 0;
final int age = 0;
A a = new A(){ @Override
public void test() {
System.out.println(age); } };
}
}
Java笔记:内部类的更多相关文章
- java 笔记(2) —— 内部类的作用
一.内部类简介 个人觉得内部类没多少研究价值,GUI中的事件响应算是非常典型的应用了. Java内部类其实在J2EE编程中使用较少,不过在窗口应用编程中特别常见,主要用来事件的处理.其实,做非GUI编 ...
- Thinking in Java 笔记
大二就买了这本书,如今再看这本书,看到了一些以前没看的细节,也有了不同的体会.本文使用第4版,整理每章的笔记心得.老外的书有个特点,他会花费大量的文字去阐述一个概念,这比堆代码强多了. 第 1 章 对 ...
- java笔记整理
Java 笔记整理 包含内容 Unix Java 基础, 数据库(Oracle jdbc Hibernate pl/sql), web, JSP, Struts, Ajax Spring, E ...
- Effective Java笔记一 创建和销毁对象
Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...
- Java学习--内部类(一)
Java学习--内部类(一) 一. 内部类的定义和特点 class Outer{ privite int num = 5; class Inner{ public void Display(){ Sy ...
- Java的内部类
Java的内部类 首先我们来了解一下什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类可以是静态static的,也可用public,default,protected和private修饰 ...
- java笔记00-目录
--2013年7月26日17:49:59 学习java已久,趁最近有空,写一个总结: java笔记01-反射:
- java使用内部类的好处及其初始化
java使用内部类的原因 每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响 java内部类初始化 ForeCatal ...
- JAVA基础——内部类详解
JAVA内部类详解 在我的另一篇java三大特性的封装中讲到java内部类的简单概要,这里将详细深入了解java内部类的使用和应用. 我们知道内部类可分为以下几种: 成员内部类 静态内部类 方法内部类 ...
- JAVA面向对象-----内部类的概述
JAVA面向对象-–内部类的概述s 将类定义在另一个类的内部则成为内部类.其实就是类定义的位置发生了变化. 在一个类中,定义在类中的叫成员变量,定义在函数中的叫成员函数,那么根据类定义的位置也可以分为 ...
随机推荐
- ArcEngine载入中SDE问题栅格数据
当直接加载矢量数据到IFeatureWorkspace接口可,但是,在装载门格当要传送的数据IRasterWorkspaceEx接口. 效果如下面的,对可以被添加到双击Globe在. watermar ...
- C---通过指针访问数组
C语言规定:如果指针变量P已指向数组中的一个元素,则P+1指向同一数组中的下一个元素. 引入指针变量后,就可以用俩种方法来访问数组元素了. 如果p的初值为&a[0],则: P+i 和a+i 就 ...
- C#中如何获取系统环境变量
原文:C#中如何获取系统环境变量 C#中获取系统环境变量需要用到Environment Class.其中提供了有关当前环境和平台的信息以及操作它们的方法.该类不能被继承. 以下代码得到%systemd ...
- JQuery slideToggle 演示简单的 Slide Panel 效果。
------------------html--------------------------------- <html xmlns="http://www.w3.org/1999/ ...
- 项目笔记---CSharp图片处理
原文:项目笔记---CSharp图片处理 项目笔记---CSharp图片处理 最近由于项目上需要对图片进行二值化处理,就学习了相关的图片处理上的知识,从开始的二值化的意义到动态阀值检测二值化等等,并用 ...
- DDD分层架构之领域实体(验证篇)
DDD分层架构之领域实体(验证篇) 在应用程序框架实战十四:DDD分层架构之领域实体(基础篇)一文中,我介绍了领域实体的基础,包括标识.相等性比较.输出实体状态等.本文将介绍领域实体的一个核心内容—— ...
- Ubuntu中改变文件的默认打开方式
其实最简单的方法是右键,在属性中修改,不过这样做没啥意义. ubuntu中与文件的打开方式相关的配置文件有四个: /etc/gnome/defaults.list 这是全局配置文件 /usr/shar ...
- leetcode 第41题 Trapping Rain Water
题目: Given n non-negative integers representing an elevation map where the width of each bar is 1, co ...
- openwrt构建过程探索
参考网站:http://wiki.openwrt.org/doc/howto/buildroot.exigence 需要下载必要的库文件,编译器等... 1 首先要获得openwrt的源码,参考ope ...
- Linux 启动过程的详细解释
对于无论什么系统, 但无法打开电源这么简单的事, 很多事情将在几秒钟内几秒钟或几十本短时间内发生, 了解这一过程将是完整的引导解决问题的任何或提高开机速度的前提. 下一个, 我们会专门寻找Linux程 ...