Java 内部类详解及其练习

学习心得

一、专业课

1内部类

1.内部类

1.1 是指在一个外部类的内部再定义一个类,类名不需要和 夹相同

1.2部类可以是静态static的,也可 publicdefaultprotectedprivate修饰(而外部类只 能使用 publicdefault

1.3注意:内部类是一个编译时的概念,一旦编译成功,就会 成为完全 不同的两类。对于一个名为outer的外部类和其内部定 义的名为 inner的内部 类。编译完成后出现outer.class outer$inner.class两类。 所以内部类的成员变量/方法名可 以和外部 类的相同

2成员内部类

成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private 的。同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取

3.局部内部类

局部内部类,是指内部类定义在方法和作用域内

4.匿名内部类
没有引用名的内部类

publicclass InnerClass {

publicstatic void main(String[] args) {

/*

* 1.内部类

* 1.1 是指在一个外部类的内部再定义一个类,类名不需要和文 件夹相同

* 1.2 内部类可以是静态static的,也可用 publicdefaultprotectedprivate修饰

* (而外部类只能使用publicdefault

* 1.3 注意:内部类是一个编译时的概念,一旦编译成功,就会 成为完全不同的两类。

* 对于一个名为outer的外部类和其内部定义的名为 inner的内部类。

* 编译完成后出现outer.classouter$inner.class两类。 所以内部类的成员变量/方法名可以和外部类的相同。

*/

Bodybody = new Body();

Body.Heartheart = new Body().new Heart(); //非静 态内部类时的声明方式

// Body.Heartheart2 = new Body.Heart(); // 注意静态内部类的生成(不需要Body后的())

heart.thump();

body.walk();

Sleepsleep = new Sleep();

sleep.sleep("yes",new YesOrNo() { //匿名内部类

@Override

publicvoid no() {

//TODO Auto-generated method stub

System.out.println("no,最多再睡三分钟");

}

@Override

publicvoid yes() {

//TODO Auto-generated method stub

System.out.println("yes,多睡六分钟");

}

});

}

}

classBody{

staticprivate int weigth;

publicvoid walk() {

inti = 2;

System.out.println("walk");

classShoes{ //成员方法中,成员内部类,只能用 default(不能写出)finali一样

publicvoid wear() {

System.out.println("blackshoes"+i); //jdk1.8开始i才不需要是final常量

}

}

//局部内部类相当于一个属性,需要在内部初始化,外部无法调用

newShoes().wear();

}

publicstatic void sWalk() {

System.out.println("staticwalk");

}

/*

* 成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成 员和方法,即使是private的。

* 同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类 的对象来获取

*/

/*static*/class Heart{ //成员位置上的内部类,成员内部类(可以 static

intrate;

/*

* 成员内部类(非静态)不能含有static的变量和方法。因为成员 内部类需要先创建了外部类,才能创建它自己的

* 静态变量需要在一个静态环境中,也就是内部类需要时静态的

*/

// staticint r;

/**

* java类加载顺序,首先加载类,执行static变量初始化,接下 来执行对象的创建,如果我们要执行代码中的变量intr 初始化,

* 那么必须先执行加载外部类,再加载内部类,最后初始化静态 变量a,问题就出在加载内部类上面,

* 不妨把内部类看成外部类的非静态成员,它的初始化必须在外 部类对象创建后以后进行,要加载内部类必须在实例化外部类之后完成,

* java虚拟机要求所有的静态变量必须在对象创建之前完成,这 样便产生了矛盾

* java常量放在内存中常量池,它的机制与变量是不同的,编 译时,加载常量是不需要加载类的,所以就没有上诉那种矛盾

*/

staticfinal int r = 2;

publicvoid thump() {

System.out.println("heartthumping");

System.out.println(weigth+Body.this.weigth);//访 问外部类属性可以用外部类.this.属性名来调用

sWalk();

walk();

classT{} //厉害了,居然还可以嵌套,但还是饶了别人把

}

}

}

classSleep{

classHeart{} //不同类下可以有重名的内部类

publicvoid sleep(String or,YesOrNo yesOrNo) {

if("yes".equals(or)) {

yesOrNo.yes();

}else{

yesOrNo.no();

}

}

interfaceYesOrNo{

voidyes();

voidno();

}

}

二、小组PK

1.我方题目

1.以下程序能否运行

如果不能请指出错在那里,

如果可以请输出程序结果:

classB extends A {

publicB() {

System.out.println("B");

}

publicvoid show(B obj) {System.out.println("B and B"); }

publicvoid show(A obj) {System.out.println("B and A");}

}

classC extends B {

Dd = new D();

classD {

D(){

show(newA());

}

}

}

publicclass A {

publicvoid show(A obj) {System.out.println("A and A");}

publicstatic void main(String[] args) {

Cc = new C();

c.show(newB());

}

}

B //创建C的实例,调用C的无参构造方法,C的默认构造方法第一条语句隐含 它的父类B的无参构造方法,所以第一个输出B

Band A //D()调用show(newA())newA()是陷阱,因为并没有调用Ashow 法。所以是调用Dshow()方法。

//D及它的外部类C中都没有定义show方法,所以找到C的父类B中,根据参数对应 输出B and A

B //c.show(newB()),调用publicB(),输出B

Band B //根据参数找到 Band B

2.请找出下面程序的错误,可能有几处(请在错误语句后面打星*):

publicclass Animal {

classAnima{

System.out.println("animal"); *//输出语句不能写在这个位置,应该写在方法 或者语句块中

}

publicstatic void main(String[] args) {

Integeri = -2;

Catcat = new Animal(); *//向下转型需要将强制类型转换

Animaldog = new Dog();

if(cat instanceof Dog) { *//eclipse编译器会报编译错误

System.out.println("cat");

}

}

}

classCat extends Animal{}

classDog extends Animal{}



3.请找出下面程序的错误,可能有几处(请在错误语句后面打星*):

publicclass Test {

inta;

voidTest(int a){ //这不是构造函数

this.a=a++;

}


publicstatic void main(String[] args) {


finalTest t = new Test(5);* //没有带参的构造函数

}

privateclass A{

Staticint a = 10; *//Static 这个不是静态关键字

System.out.println(a); *

public void getA(final Test t){

t= new Test(6); *

System.out.println(t.a);

}

}


}


4.程序是否能够运行,如果能运行结果是什么?不能请说明理由

注意输出格式

publicclass Question {

publicstatic void main(String[] args) {

Aa = new B();

System.out.println(a.method1('c'));

a.fun(); ***

}

}

classA{

staticint i;

inta = 10;

{

i= method1('d');

}

public int method1(char c){

if(c> 0){

returni + a;

}

return0;

}

staticvoid method(){

i++;

}

}

classB extends A{

public void fun(){

System.out.println(i);

A.method();

}

}


程序不能运行,在带*出对象a不能调用fun()方法,因为父类A里面没有fun方法, 所以A类的引用找不到fun方法,报错。


5.分别用恶汉式和 懒汉式 实现单例设计模式 intage 方法名自拟


classSingle{

privateint age;

privateSingle() {

super();

}

publicint getAge() {

returnage;

}

publicvoid setAge(int age) {

this.age= age;

}

privatestatic Single s = new Single();

publicstatic Single getInstances(){

returns;

}

}


classSingle2{

privateint age;

privateSingle2() {

super();

}

publicint getAge() {

returnage;

}

publicvoid setAge(int age) {

this.age= age;

}

privatestatic Single2 s = null;


publicsynchronized static Single2 getInstances(){

if(s== null){

s= new Single2();

}

returns;

}

}

2、对方题目

1publicclass Demo03 extends S{


publicfinal void mb_method(int i){

System.out.println(i);

}

publicstatic void main(String[] args) {

//TODO Auto-generated method stub

Demo03demo01 = new Demo03();

demo01.mb_method();

demo01.mb_method(2);

}


}

classS{

publicfinal void mb_method(){

System.out.print("1");

}

}

A.程序可以通过编译,并正常运行输出“12”

B.程序可以通过编译,但无法正常运行

C.程序无法通过编译,因为方法调用有问题

D.程序无法通过编译,因为具有final属性的方法不能被覆盖

A


2父类为Person,子类为Student,父类中有一个使用private修饰的属性school,student的对象想要修 改该属性的值为“新东方”并且获取该属性打印出来,该如何实现?请完整下列程序程序。

classPerson{

privateString school;

}


classStudent extends Person{

publicstatic void main(String[] args) {

Personstudent = new Student();

}

}



答案:

Person类中:

publicvoid changeSchool(String school){

this.school= school;

}

publicString outName(){

returnthis.school;

}


Student类中:

student.changeSchool("新东方");

Stringname = student.outName();

System.out.println(name);


3.抽象方法不能用privatefinal修饰,那么是否能用static呢?请说明原因。

(提示,抽象的概念)


抽象方法的概念:

当一个类里面有某个行为(方法),子类中该方法具体的实现方式不明确的时候,

但不明确要求该方法要重写,就需要该类对这个方法进行模板提示,所需具体实现方式交给子类去实现。

static的成员是在程序执行到main时就已经确定的。


4.

1public class Test {

2 publicstatic void main(String[] args) {

3 Dogdog = new Dog();

4 Catcat = new Cat();

5 Animal[]animal = new Animal[]{dog,cat};

6 cat= (Cat)animal[0];

7 System.out.println(cat.name);

8 }

9}


//animal是超类 CatDog都是animal的子类

classAnimal{

Stringname = "皮皮虾";

}

classCat extends Animal{

Stringname = "香蕉船";

}

classDog extends Animal{

Stringname = "象拔蚌";

}


A第五行编译不能通过;

B第六行编译不能够通过;

C编译能通过,运行异常;

D能运行,输出皮皮虾;

E能运行,输出香蕉船;

F能运行,输出象拔蚌;



答案:C

原因:animal[0]对应的是dog,是Dog类型,与Cat没有继承或实现关系,所以不能强转,运行时会报类转换 异常


5.

懒汉式单例 手写代码


publicclass A{

privatestatic A a = null;

privateA(){


}

publicstatic A getInstance(){

if(a== null){

a=new A();

}

returna;

}


}


学习心得:

1.一个人虽然能走得快,但一群人才能走得远



  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值