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.权限修饰符的范围

关系同包当前类同包的子类/无关类不同包子类 不同包无关类
privateY
默认修饰符YY
protectYYY
publicYYYY

         四个权限修饰符的优先级(从大到小)
                 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() ;}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部