c语言/c++转Java学习笔记---进阶问题

  • 1.字段变量与局部变量
  • 2.虚方法
  • 3.构造方法
  • 4.初始化
  • 5.构造方法的执行过程
  • 6.对象清除与垃圾回收
  • 7.内部类和匿名类
  • 8.Lambda表达式
  • 9.装箱、枚举、注解
  • 10.引用与指针
  • 11.相等还是不等


1.字段变量与局部变量

  • 前者是在类中,后者是在方法中定义的变量或方法的参变量
  • 存储位置,字段变量为对象的一部分、存在于堆中,局部变量是存在于栈中的,局部变量是存在于栈中的。
  • 初始值:字段变量可以自动赋值,局部变量须显式赋值
  • 字段变量属于类,可以用public,private,static,final修饰
  • 局部变量不能被访问控制符及static修饰
  • 格式:变量 instanceof 类型(结果是Boolean值)

2.虚方法

  • java中普通的方法是虚方法
  • 但static,private方法不是虚方法调用
  • static,private与虚方法编译后的指令是不同的
  • static的方法,以声明类型为准,与实例类型无关
  • private方法子类看不见,也不会被虚化
  • final方法子类不能覆盖,不存在虚化问题`

3.构造方法

  • 对象都有构造方法
  • 如果没有,编译器加一个default构造方法
  • 调用本类或父类的构造方法
    this调用本类的构造方法
    super调用直接父类的构造方法
    this或super要放在第一条语句,且只能够有一条
  • 如果没有this及super,则编译器自动加上super(),即调用直接父类不带参数的构造方法
  • 因此必须令所有父类的构造方法都得到调用,否则整个对象的构建就可能不正确

4.初始化

1.创建对象时初始化,如

Person p = new Person(){{age=18;name="李明"}};
  • 这样可以针对没有构造函数,但又要赋值
  • 注意两个大括号

2.实例初始化

  • 在类中直接写
    {语句}
  • 实例初始化,先于构造方法{}中的语句执行

3.静态初始化

  • static{语句}
  • 静态初始化,在第一次使用这个类的时候执行
  • 先于实例初始化执行

5.构造方法的执行过程

  • 就单个的类来讲,执行顺序是 静态初始化块 -> 初始化块 -> 构造器
  • 构造方法执行过程遵循以下步骤
    1.调用本类或父类的构造方法,直至最高一层(Object)
    2.按照声明顺序执行字段的的初始化
    3.执行构造函数中的各语句
    总结:先父类构造,再本类成员赋值,最后执行构造方法中的语句

6.对象清除与垃圾回收

1.垃圾回收是由java虚拟机的垃圾回收线程来完成的,任何对象都有一个引用计数器,当其值为0时,说明该对象可回收
2.System.gc()方法
system类的static方法,可以要求系统进行垃圾回收
3.java中没有“析构方法”,但Object的finalize()有类似功能

  • 系统在回收时会自动调用对象的finalize()方法。
    protected void finalize() throws Throwable{}
  • 子类的finalize()方法
    可以在子类的finalize()方法释放系统资源
    一般来说子类的finalize()方法应该调用到父类的finalize()方法,以保证父类的清理工作能够正常进行

4.try-with-resources

  • 对于实现了java.lang.AutoCloseable的对象
    try(Scanner scanner= new Scanner(…)){…}
    会自动调用close()方法,相当于finally{Scanner.close()};

7.内部类和匿名类

  • 内部类是在其他类中的类
  • 匿名类是一种特殊的内部类,它没有类名

1.内部类

  • 内部类不能与外部类同名
  • 内部类中可以直接访问外部类的字段及方法
  • 如果内部类中有与外部类同名的字段或方法则可以用,外部类.this.字段及方法
  • 内部类与类中的字段、方
  • 法一样都是外部类的成员,它的前面也可以有访问控制符和其他修饰符
  • 用static修饰内部类 表面该内部类实际是一种外部类

2.局部类

  • 在一个方法中也可以定义类,这种类称为“方法中的内部类”,或者叫局部类

3.匿名类

  • 匿名类是一种特殊的内部类,它没有类名,在定义类的同时就生成该对象的一个实例(一次性使用的类)
  • 不取名字,直接用其父类或接口的名字
  • 类的定义的同时就创建实例,即类的定义的前门有一个new
  • 在构造对象的时候使用父类构造方法
  • 应用:1.注册事件监听器 2.作为方法的参数(排序时比较大小接口)

8.Lambda表达式

1.基本写法:(参数)->结果

  • 大体上相当于其他语言的“匿名函数”或“函数指针”
  • 在线程的例子中new Thread (()->{...}).start
  • 在积分的例子中`d=Integral(x->Math.sin(x),0,1,EPS);
  • 在按钮处理事件中 btn.addActionListener(e->{…});

2.能写成Lambda的接口的条件

  • 由于Lambda只能表示一个函数,所以能写成Lambda的接口要求包含且最多只能有一个抽象函数
  • 这样接口可以用@FunctionalInterface来表示。称为函数式接口
@FunctionalInterface
interface Fun{double fun(double x);}

9.装箱、枚举、注解

1.基本类型的包装类将基本类型包装成Object(引用类型)
例如

package com.demo;
// 以int数据为例实现一个包装处理的定义
class Int {
    private int data ; //包装了一个基本数据类型
    public Int(int data) {
        this.data = data ;
    }
    public int intValue() {
        return this.data ;
    }
}
public class BaoZhuang {
    public static void main(String[] args) {
        //装箱——将基本数据类型保存在包装类之中
        //Int temp = new Int(10) ;
        Object obj = new Int(10) ;
        //拆箱——从包装类对象中能够获取基本数据类型
        //int x = temp.intValue() ;
        int x = ((Int)obj).intValue() ;
        System.out.println(x * 2) ;        
    }
}

2.枚举

  • 枚举(enum)是一种特殊的class类型
enum Light{Red,Yellow,Green};
Light light=Light.Red

也可以在enum定义体中,添加字段、方法构造方法
3.注解

  • 注解又称为注记、标记、标注、注释,是在各种语法要素上附加信息,以供编译器或其他程序使用
  • 所有的注解都是java.lang.annotation.Annotation的子类
  • 常用的注解如
    @Override 表示覆盖父类的方法
    @Deprecated 表示过时的方法
    @SupppressWarnings 表示让编译器不产生警告

10.引用与指针

  • Java中没有指针,引用的实质就是指针,但他是受控的、安全的
  • C语言指针在java中的体现
    (1)传地址->对象
    (2)指针运算->数组
    (3)函数指针->接口Lambda表达式
    (4)指向节点的指针->对象的引用
    (5)使用JNI
    Java Native Interface(JNI)
    它允许Java代码和其他语言写的代码进行交互

11.相等还是不等

1.数值类型:转换后比较
2.浮点数:判断两个数的相差是不是很小
3.boolen类型无法与int比较

Integer i= new Integer(10);
Integer j= new Integer(10);
System.out.println(i==j);//false因为对象是两个

Integer i= 10;
Integer j= 10;
System.out.println(i==j);//应为对象有缓存(-128到127有)

Integer i= 200;
Integer j= 200;
System.out.println(i==j);//false因为对象是两个

4.枚举类型:内部进行了唯一实例化,所以可以判断
5.引用对象:
是直接看两个引用是否一样
如果要判断内容是否一样,则要重写equals方法
如果重写equals方法,则最好重写hashCode()方法
6.String对象
判断相等,一定不要用==,要用equals
但是字符串常量及字符串常量会进行内部化(interned)相同的字符串常量是 相等 的

String hello="Hello",lo="lo";
System.out.println(hello=="Hello");//true
System.out.println(Other.hello=="Hello");//true

System.out.println(hello=="Hel"+"lo");//true
System.out.println(hello=="Hel"+lo);//false
System.out.println(hello==new String("Hello"));//false
System.out.println(hello==("Hel"+lo).intern);//true