Java学习总结4
1.static关键字的引入
我们先来看一段代码
//定义一个人类Person
class Person{String name ; //姓名int age ; //年龄String country ; //国籍//无参构造方法public Person(){}//带三个参的有参构造方法public Person(String name,int age,String country){this.name = name ;this.age = age ;this.country = country ;}//提供带两个参的有参构造方法:name,agepublic Person(String name,int age){this.name = name ;this.age = age ;}//提供show方法,来展示人的信息...public void show(){System.out.println("姓名:"+name+",年龄是:"+age+",国籍是:"+country);}
}//测试类
public class Test {public static void main(String[] args) {// 有参构造方法赋值(3个参数的)Person p1 = new Person("张三",25,"中国") ;p1.show() ;System.out.println("-----------------------------------------");Person p2 = new Person("赵四",18,"中国") ;p2.show();System.out.println("-----------------------------------------");Person p3 = new Person("王五",20,"中国") ;p3.show();}
}
通过带三个参数的有参构造直接赋值,三个人都是 "中国":
1)代码层面:
代码冗余(重复了)
2)从内存角度考虑:
在堆内存中浪费空间,每一个堆内存中的变量都有自己的空间值.
Java提供给了关键字: static 基本的概念:共享,共用(可以被多个对象共用!).被静态修饰的东西是随着类的加载而加载.
class Person{String name ; //姓名int age ; //年龄//String country ; //国籍//静态修饰static String country ;//静态的成员变量//无参构造方法public Person(){}//带三个参的有参构造方法public Person(String name,int age,String country){this.name = name ;this.age = age ;this.country = country ;}//提供带两个参的有参构造方法:name,agepublic Person(String name,int age){this.name = name ;this.age = age ;}//提供show方法,来展示人的信息...public void show(){System.out.println("姓名:"+name+",年龄是:"+age+",国籍是:"+country);}
}//测试类
public class Test {public static void main(String[] args) {Person p1 = new Person("王昭君",2) ;p1.show() ;Person p2 = new Person("西施",18) ;p2.show();Person p3 = new Person("貂蝉",20) ;p3.show();}
}
2.静态变量和成员变量的区别
(1)数据储存区域的区别:
静态变量:存储在方法区中的共享内存区域的静态区域中(static区域中);
成员变量:在堆内存中;
(2)别名不同
静态变量:跟类有关系(类加载,静态的东西先进内存)----->"类成员"
成员变量:对象的特有属性------>"实例变量"
(3)生命周期不用
静态变量:随着类的加载而加载,随着类的加载完毕,进入static区域中,消失了.
成员变量:随着对象的创建而存在,随着对象的创建完毕,等到垃圾回收器空闲时间回收.
(4)调用方式不同
静态变量:既可以使用对象名访问,也可以使用类名访问,推荐使用类名访问;
成员变量:只能使用对象名来访问.
3.继承
3.1 定义
将多个类的共性内容抽取出来,放在一个独立类中,让这个独立的类和这多个类产生一种"继承"的关系 .
格式:
class 子类名 extends 父类名{
}
//父类: Person
class Person{//吃public void eat(){System.out.println("饿了就需要吃饭...");}//睡public void sleep(){System.out.println("困了就需要休息...");}//玩public void play(){System.out.println("学习困了就需要劳逸结合...");}
}//子类:学生类
class Student extends Person{//特有功能public void study(){System.out.println("学习JavaEE...");}
}
//子类:老师类
class Teacher extends Person{public void teach(){System.out.println("讲解JavaEE...");}
}
//子类:程序员类
class Programmer extends Person{public void code(){System.out.println("日日夜夜写代码...");}
}//测试类
public class ExtendsDemo1 {public static void main(String[] args) {//没有使用继承之前的测试://创建学生类对象Student s = new Student() ;s.eat() ;s.sleep() ;s.play() ;s.study(); //特有功能System.out.println("------------------------------------------");//创建老师类对象Teacher t = new Teacher() ;t.eat();t.sleep();t.play();t.teach();//特有功能System.out.println("------------------------------------------");//创建程序员类Programmer programmer = new Programmer() ;programmer.eat();programmer.sleep();programmer.play();programmer.code(); //特有功能}
}
3.2 继承的好处
1)提高了代码复用性
2)提高了代码的维护性
3)类与类产生的这种关系"继承",是多态的前提条件!
3.3 继承的弊端
开发的设计原则:低耦合,高内聚
耦合:类与类之间的关系
内聚:指的是执行某件事情的能力
低耦合:关系越简单越好,否则.如果继承关系的多,一个父类的存在问题,其他类出现问题.
3.4 继承的特点
1)在Java语言中,类与类之间的继承关系,只支持单继承.
在有的语言支持这种格式
class Zi extends Fu1,Fu2{}... (Java中不支持类和类之间多继承)
2)虽然类与类之间只支持单继承,但是可以多层继承.
3.5注意事项
1)子类继承父类,只能继承父类非私有的成员,私有的成员可以间接通过公共访问访问!
因为私有成员,只能在本类访问,外界类不能访问!
2)子类继承父类,不能继承父类的构造方法,但是可以通过super访问.
//定义一个父类
class Fu {//先提供父类的无参构造方法public Fu(){System.out.println("Fu的无参构造方法...") ;}
}//定义一个子类
class Zi extends Fu{//子类的无参构造方法public Zi(){//super(); //可以省略不写,默认的!System.out.println("Zi的无参构造方法...") ;}//提供子类的有参构造方法public Zi(String name){//super() ;可以省略不写,默认的!System.out.println("Zi的有参构造方法...");}
}
//测试类
public class ExtendsDemo1{public static void main(String[] args) {//创建子类对象Zi zi = new Zi() ;System.out.println("----------------------------") ;Zi zi2 = new Zi("hello") ;}
}
3.6 子父的继承关系中,成员变量的访问问题
情况1:
子类继承父类,子类的成员变量名称和父类的成员变量名称不一致的情况:很简单,分别调用即可
情况2:
子类继承父类,子类的成员变量名称和父类的成员变量名称一致的情况:遵循 "就近原则"
1)现在子类的局部位置中找,如果存在,就使用
2)如果不存在,那么就在子类的成员位置中找,如果存在,就使用
3)如果子类的成员位置中不存在,那么就在父类的成员位置中找,如果存在,就使用
4)如果父类的成员位置中不存在,那么就报错了,压根不存在这个变量
情况1:
//定义一个父类
class Fu{//父类的成员变量int num = 100 ;}//定义一个子类
class Zi extends Fu{//子类的成员变量名称和父类的成员变量名称一致//子类的成员变量
// int num = 200 ;//子类的成员变量名称和父类的成员变量名称不一致int num2 = 200 ;//成员方法public void show(){//子类的局部位置int num = 30 ;System.out.println(num) ;// System.out.println(num2);}
}//测试类
public class Test {public static void main(String[] args) {//创建子类对象//情况1:Zi zi = new Zi() ;System.out.println(zi.num);System.out.println(zi.num2);zi.show();}
}
情况2:
//定义一个父类
class Fu{//父类的成员变量int num = 100 ;}//定义一个子类
class Zi extends Fu{//子类的成员变量名称和父类的成员变量名称一致//子类的成员变量int num = 200 ;//子类的成员变量名称和父类的成员变量名称不一致int num2 = 200 ;//成员方法public void show(){//子类的局部位置int num = 30 ;System.out.println(num) ;System.out.println(num2);}
}//测试类
public class Test {public static void main(String[] args) {//情况2://创建子类对象Zi zi = new Zi() ;zi.show() ;}
}
3.7 方法重写
子类继承父类的时候,子类的出现了和父类一模一样的方法声明,这个子类的功能将父类的功能覆盖掉,使用自己的业务功能完成.
英文单词:override
目的:使用子类的功能,将父类的功能覆盖掉
//手机类Phone
class Phone{//功能:打电话public void call(){System.out.println("手机可以打电话了...");}
}
//新的手机类NewPhone
class NewPhone extends Phone{//callpublic void call(){super.call() ;System.out.println("手机可以看天气预报了") ;System.out.println("手机还可以微信聊天了...") ;}
}//测试类
public class ExtendsDemo {public static void main(String[] args) {//创建子类对象NewPhone np = new NewPhone() ;np.call() ;}
}
4.final关键字
定义: final:最终的,无法更改的(状态修饰符)
特点:
1)可以修饰类,该类不能被继承,它不能在进行扩展了...
举例:后面常用类中重要的类String: 被final修饰
2)可以修饰变量,此时这个变量是一个常量:自定义常量
3)可以修饰成员方法,此时这个方法不能被重写.
应用场景 自定义常量使用居多;
final会结合static一块使用(static修饰:可以类名直接调用)
public static final int num = 100 ; //修饰基本数据类型 :编译时期常量 (Jvm不需要加载)
//Integer:int类型的包装类类型(引用类型)
public static final Integer i = new Integer() ;//修饰的引用数据类型 :运行时期常量(JVM需要加载类)
final修饰的基本数据类型和修饰引用数据类型的区别?
修饰的基本数据类型:基本数据类型的值不能在改变,只能赋值一次,此时这种常量,称为"编译时期常量",Jvm只是检查语法,是不需要加载的.
修饰的引用数据类型:引用数据类型的空间地址值不能在改变,但是里面的成员变量(没有加入final)依然可以使用这种常量,Jvm加载引用数据类型,属于"运行时期常量".
传统方式的自定义常量
public static final 基本数据类型 变量名 = 常量值 ;
5.多态
什么是多态
现实世界事物描述:一个事物体现出的的不同形态(内存中)
从程序中描述:这个对象在内存中的变化
猫是猫 :Cat c = new Cat() ;
猫是动物 :Animal a = new Cat() ;
多态的前提条件:
1)必须存在继承关系, 如果没有继承,谈不了多态! (继承的好处第三点)
2)必须存在方法重写,需要让子类完成自己的业务功能,需要将父类的某些功能进行覆盖(重写)
3)需要存在"父类引用指向子类对象"
格式: Fu fu =new Zi() ;
父类名 对象名 = new 子类名() ; "向上转型"(使用的是父类的东西).
多态的中的成员访问特点
格式: Fu fu =new Zi() ;
父类名 对象名 = new 子类名() ; "向上转型"(使用的是父类的东西)
成员变量:
编译看左,运行看左! (如果编译通过了,说明Fu中存在变量,运行看左,使用父类的东西)
成员方法:(非静态的)
编译看左,运行看右(因为子类出现了父类一模一样的方法声明,覆盖了)
静态的成员方法:算不上方法重写.和类相关的.称为"类成员" 编译看左,运行看左!
随着类的加载而加载,访问通过类名访问
构造方法:
因为存在继承关系,存在无参构造/有参构造,都需要父类先初始化,然后才是子类,分层初始化
//父类
class Fu{int num = 10 ;public void show(){System.out.println("show Fu") ;}public static void method(){System.out.println("method Fu...");}public Fu(){System.out.println("Fu...");}
}
class Zi extends Fu{int num = 20 ;//重写了@Overridepublic void show() {System.out.println("show Zi") ;}public static void method(){System.out.println("method Zi...");}public Zi(){System.out.println("Zi");}
}
public class DuoTaiDemo {public static void main(String[] args) {//需要存在"父类引用指向子类对象"Fu fu = new Zi() ; //父类的引用fu---堆内存中创建的它的子类对象//访问成员变量System.out.println(fu.num) ;fu.show() ;// fu.method() ;//静态方法推荐方式:/* Fu.method() ;Zi.method();*/}
}
多态的好处是什么?
1)可以提高代码的复用性(继承保证的)
2)可以提高代码的扩展性(由多态的保证:Fu fu = new Zi() 父类引用指向子类对象)
多态的弊端:
格式:Fu fu = new Zi() :向上转型 (使用的是父类的东西)
不能访问子类的特有功能. 如何解决?
1)直接创建具体的子类: 子类new 子类
从内存角度考虑: 需要在堆内存中继续开辟空间,消耗内存空间
2)优化内存:
将父类的引用强转子类引用 向下转型
Fu fu = new Zi();
Zi zi = (Zi)fu;
//父类
class Father{public void study(){System.out.println("搞科学研究工作....");}
}
//子类
class Son extends Father{@Overridepublic void study() {System.out.println("学习JavaEE...");}//特有功能public void playGame(){System.out.println("会玩英雄联盟...");}
}//测试类
public class DuoTaiDemo3 {public static void main(String[] args) {//多态的格式:父类引用指向子类对象Father f = new Son() ;f.study() ; //编译看左,运行看右//f.playGame() ;不能访问子类的特有功能System.out.println("-----------------------------------") ;// 1)直接创建具体的子类: 子类new 子类Son s = new Son() ; //需要在堆内存中继续开辟空间,消耗内存空间s.playGame() ;System.out.println("-----------------------------------") ;//向下转型:将父类的引用强转子类引用 :相对1)方式来说,节省内存//前提条件:必须存在向上转型Son son = (Son) f;son.playGame() ;}
}
6.抽象类
定义
在现实事物中,将比较概括性的事物统称为"抽象的事物".猫和狗是具体的动物了,他们都继承自动物类,将动物就可以看成是一个抽象的事物.猫和狗具体的功能应该具体体现,在动物事物中,应该给出一个声明即可,不需要具体体现!
格式: abstract class 类名{}
抽象类的注意事项:
1)在一个类中,如果当前类中存在抽象功能(方法),那么这个类必须抽象类;
2)一个抽象类中,不一定都都是抽象方法;
抽象方法:没有方法体的一个成员方法,并且携带一个关键字 abstract
权限修饰符 abstract 返回值类型 方法名(形式参数列表) ;
3)抽象类的子类:
为抽象类;定会存在具体的子类,否则没有意义.
为具体类:它才有意义,可以创建实例.
4)抽象类的本质:
强制子类必须完成的事情.
抽象类特点:不能实例化 (不能创建对象)
//抽象的动物类
abstract class Animal{//动物需要吃饭//抽象方法public abstract void eat() ;public abstract void sleep() ;//非抽象方法public String many(){return "动物有很多种" ;}
}//研究的都是抽象的类的子类:具体类
class Cat extends Animal{ //才是有意义的...@Overridepublic void eat() {System.out.println("猫吃鱼...") ;}@Overridepublic void sleep() {System.out.println("猫趴着睡觉...") ;}//特有功能public void playGame(){System.out.println("猫玩老鼠...");}
}//具体的狗类
class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗吃骨头...");}@Overridepublic void sleep() {System.out.println("狗躺着睡觉...");}//特有功能public void lookDoor(){System.out.println("狗看门...");}
}//测试类
public class AbstractDemo {public static void main(String[] args) {//子类是具体类:可以实例化Animal a = new Cat() ; //抽象类多态a.eat() ;a.sleep() ;String result = a.many();System.out.println(result);// a.playGame() ;//向下转型Cat c = (Cat) a ;c.playGame() ;System.out.println("--------------------------------------") ;a = new Dog() ; a.eat() ;a.sleep() ;
// a.lookDoor() ;Dog dd = (Dog) a;dd.lookDoor() ;}
}
abstract和哪些关键字冲突
private:被private修饰的方法只能在本类访问, 有一个abstract关键字:强制子类重写
final:被final修饰的成员方法,不能被重写,而abstract强制子类重写
static:被static修饰符的方法,需要被类名访问,随着类的加载而加载,而abstract需要让子类重写这个方法
7.接口
什么是接口:
接口实际就是描述事物本身之外的"额外功能(扩展功能)
格式:
关键字interface 接口名{} 接口的命名规则和类一样,"大驼峰命名法"
抽象类的特点:
1)不能实例化
2)接口中成员方法:只能是抽象方法,不能有方法体
接口如何实现呢? 接口是比抽象类还抽象的一种概念!
接口的子类------>子实现类 (接口和实现类: 实现关系 : implements)
注意事项:
1)接口的子类可能是抽象类,那么肯定会存在最具体的子类,否则 没有意义!
2)具体类:就通过接口多态进行实例化!
接口名的 对象名 = new 子实现类名() ;
//定义一个接口:跳高接口
interface Jump{/* public abstract void jump(){ //接口的方法不能有方法体}*/public abstract void jump() ;//跳高功能:抽象方法
}//接口的子类---子实现类,它和接口的关系:implements:实现
//如果为抽象类
/*abstract class Cat implements Jump{public void jump(){System.out.println("猫可以跳高了...");}}*///研究的是具体的子实现类
class Cat implements Jump{@Overridepublic void jump() {System.out.println("猫可以跳高了...");}
}//测试类
public class InterfaceDemo {public static void main(String[] args) {//接口不能实例化// Jump jump = new Jump() ; //Jump是抽象的,不能实例化(接口是一个特殊的抽象类)//父类引用指向子类对象:// Jump jump = new Cat() ; //接口的子类是抽象类,没有意义,不能new ,肯定存在具体的子类//研究的是具体的子实现类Jump jump = new Cat() ;//Jump是接口: 接口多态!jump.jump();}
}
8.接口和抽象类的区别
1) 成员的的区别;
接口:
成员变量:只能是常量,存在默认修饰符 public static final可以省略.
成员方法:只能是抽象方法,存在默认修饰符 public abstract 可以省略;
接口没有构造方法
抽象类:
成员变量:既可以是常量,也可以是变量
成员方法:既可以存在抽象方法,而且抽象方法abstract不能省略,也可以存在非抽象方法.
构造方法:存在无参/有参,继承关系,先让父类初始化,然后是子类初始化(分层初始化)
2)关系的区别
类与类之间的关系:继承关系 extends,只支持单继承,不支持多继承,但是可以多层继承.
类与类之间的关系:实现关系 implements,一个类继承另一个类的同时,可以实现多个接口;
接口与接口之间的关系:继承关系,不仅支持单继承,也可以多继承,也可以多层继承.
3)设计理念的区别:
抽象类:存在继承关系extends,继承体现的是"is a"的关系;
接口:存在实现关系implements,仅仅是将额外功能提供相关的事物,这个事物要具备额外功能.
必须实现这个接口,体现的是一种"like a"的关系.
9.形式参数问题
如果方法的形式参数是基本数据类型,实际参数需要传递当前具体的基本类型的数值即可.
如果方法的形似参数是引用数据类型
具体类:调用该方法,实际参数需要传递的是当前具体类对象.
class Student{public void study(){System.out.println("学习JavaEE...");}
}
class StudentDemo{//成员方法public void method(Student student){ //形式参数是引用类型:Student:具体类---->实际参数需要创建Student类的具体对象student.study() ;}
}
//测试类
public class ArgsDemo1 {public static void main(String[] args) {//需要调用StudentDemo类中的method方法//创建StudentDemo类的对象StudentDemo sd = new StudentDemo() ;sd.method(new Student());//匿名对象System.out.println("---------------------------") ;//方式2:创建一个学生对象Student s = new Student() ;sd.method(s) ;}
}
抽象类: 调用该方法,实际参数需要传递的是当前抽象类的子类对象,抽象类多态完成.
abstract class Person{//定义一个非抽象方法/*public void work(){System.out.println("人都需要工作...");}*/public abstract void work() ;
}
//定义一个类
class PersonDemo{//成员方法public void show(Person person){//方法的形式参数是引用类型:抽象类--->调用该方法实际参数需要传递当前抽象类的子类对象:抽象类多态person.work() ;}
}//抽象类不能new,需要将具体的子类定义出来
//程序员
class Programmer extends Person{@Overridepublic void work() {System.out.println("程序员日日夜夜敲代码...");}
}
//经理
class Manager extends Person{@Overridepublic void work() {System.out.println("不断的谈需求,解决技术难点...");}
}//测试类
public class ArgsDemo2 {public static void main(String[] args) {//需求:调用PersonDemo类中的show方法PersonDemo pd = new PersonDemo() ;//Person p = new Person() ; //抽象类不能实例化//抽象类多态Person p = new Programmer() ;//向上转型pd.show(p) ;Person p2 = new Manager() ;pd.show(p2) ;System.out.println("-------------------------------------") ;//匿名对象pd.show(new Manager()) ;pd.show(new Programmer()) ;}
}
接口:调用该方法,实际参数需要传递的是当前接口的子实现类对象:接口多态
class StudyDemo{public void function(Love love){//方法的形式参数是引用类型:接口,//调用该方法,实际参数需要传的是当前接口的子实现类对象:接口多态love.love() ;}
}
//子实现类
class StudyImpl implements Study{@Overridepublic void study() {System.out.println("学生就要努力学习");}
}//测试类
public class ArgsDemo3 {public static void main(String[] args) {//需求:调用StudyDemo类中的functionStudyDemo sd = new StudyDemo() ;//Study s = new Study() ;//接口不能实例化Study s = new StudyImpl() ; //接口多态ld.function(s) ;System.out.println("------------------------") ;//匿名对象new StudyDemo().function(new StudyImpl());}
}
10.instanceof判断
格式:对象名称 instanceOf 类名
判断当前对象名是否当前类的实例
//父类
class Animal{}
//子类
class Cat extends Animal{}class Dog extends Animal{}
//测试类
public class InStanceOfDemo {public static void main(String[] args) {//创建子类对象Cat cat = new Cat() ;//多态测试Animal a = new Dog() ;//多态//instanceof:判断当前某个对象名是否是某个类的实例if(cat instanceof Cat){System.out.println("这是一个猫的实例");}else if(a instanceof Dog){System.out.println("这是狗的实例...");}}
}
11.返回值问题
如果方法的返回值类型是基本数据类型:最终通过功能的业务操作,返回的数据结果.
例如:
public int sum(int a,int b){}
如果方法的返回值类型是引用数据类型
具体类:
class Student{public void study(){System.out.println("学习JavaEE...");}
}
class StudentDemo{//定义一个成员方法public Student method(){//返回值类型时一个引用类型:具体类, 调用该方法的时候,需要返回的当前具体类对象!// return Student ;//方式1:有名字对象// Student s = new Student() ;// return s ;//方式2:匿名对象return new Student() ;}
}
//测试类
public class ReturnDemo {public static void main(String[] args) {//需求:调用StudentDemo类的method方法StudentDemo sd = new StudentDemo() ;Student student = sd.method();//这个方法完成事情 Student student = new Student() ;student.study() ;}
}
抽象类:如果一个方法的返回值是一个抽象类型,那么该方法需要返回当前抽象类的子类对象
抽象类多态.
abstract class Person{//抽象方法public abstract void work();}
class PersonDemo{public Person show(){//??// Person person = new Person() ;//抽象类不能new ,不能实例化,只能 通过抽象类多态,子类进行实例化//方式1:抽象类多态//Person p = new Worker() ;//return p ;//方式2:匿名对象return new Worker() ;}
}//定义Person类的子类
class Worker extends Person{@Overridepublic void work() {System.out.println("爱生活,爱Java...");}
}
//测试类
public class ReturnDemo2 {public static void main(String[] args) {//需求:调用PersonDemo类中的show方法()PersonDemo pd = new PersonDemo() ;Person person = pd.show(); //实际业务: Person person = new Worker() ;person.work() ;}
}
接口 :如果一个方法的返回值是接口类型,那么该方法需要返回的是当前接口的子实现类对象
接口多态.
interface Study{void study() ;
}
class StudyDemo{public Study function(){//方法的返回值是一个接口类型,接口不能实例化,需要返回的当前接口的子实现类对象//?//方式1://接口多态// Study study = new StudyImpl() ;// return study ;//匿名对象return new StudyImpl() ;}
}//定义子实现类
class StudyImpl implements Study{@Overridepublic void study() {System.out.println("study studyImpl...");}
}//测试类
public class ReturnDemo3 {public static void main(String[] args) {//测试调用:StudyDemo中的function方法:StudyDemo studyDemo =new StudyDemo() ;Study study = studyDemo.function();study.study();}
}
11.权限修饰符的范围
| 关系 | 同包当前类 | 同包的子类/无关类 | 不同包子类 | 不同包无关类 |
|---|---|---|---|---|
| private | Y | |||
| 默认修饰符 | Y | Y | ||
| protect | Y | Y | Y | |
| public | Y | Y | Y | Y |
四个权限修饰符的优先级(从大到小)
public protected 默认修饰符 private
12.内部类
在一个类A中定义另一个类B,那么将类B就称为类A的内部类,类A是它的外部类!
内部类:
成员内部类:在一个类的成员位置定义的
局部内部类:在一个类的成员方法中定义的类
局部内部类的也是内部类的一种
特点:
局部内部类可以访问外部类的成员,包括私有.
局部内部类访问局部变量的时候,有什么要求?为什么?
要求当前的局部变量为常量:加入final修饰 ,为什么
jdk8 jvm已经做了内存优化:通过反编译工具查看:num2:自动带上final修饰(默认,省略了)
jdk7以前(包含jdk7):局部内部类访问局部变量,前面必须显示的加入final修饰
局部变量的生命周期随着方法的调用而存在,随着方法调用结束而消失;
但是局部变量还在被局部内部类的成员方法在使用,局部类的对象不会立即消失,需要等待GC回收,需要将这个变量变成常量,保证一直可以访问到.
//外部类
class Outer{private int num = 20 ;// private int num2 = 50 ;//私有//成员方法public void method(){//局部变量final int num2 = 100 ; //jdk8 jvm已经做了内存优化:通过反编译工具查看:num2:自动带上final修饰(可以省略:优化过了)//定义局部内部类class Inner{//成员方法public void show(){//访问局部变量num3System.out.println(num) ;System.out.println(num2) ; //还在使用变量num2// System.out.println(num2) ;}}//外部类的当前这个成员方法中:创建局部内部类对象,调用showInner inner = new Inner() ;inner.show();}
}//测试类
public class InnerClassDemo1 {public static void main(String[] args) {//创建外部类对象Outer outer = new Outer() ;outer.method() ;}
}
内部类的另一种格式:(重点)
匿名内部类:没有名字的类
格式:
new 类名/接口名(){ 一般类名--->抽象类
重写抽象方法(){
业务功能;
}
} ;
匿名内部类的本质:
就是继承了该抽象类或者实现了该接口子类对象.
//定义一个接口
interface Inter{//只有一个抽象方法void show() ;//多个抽象方法void show2() ;
}//定义一个外部类
class Outer{//有一个成员方法public void method(){Inter inter = new Inter() {//接口多态方式:不过子实现类没类名@Overridepublic void show() {System.out.println("show Inter...");}@Overridepublic void show2() {System.out.println("show2 Integer...");}};inter.show() ;inter.show2() ;}
}
//测试类
public class NoNameInnerClassDemo {public static void main(String[] args) {//创建外部类对象Outer outer = new Outer() ;outer.method() ;}
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
