java(匿名函数、方法引用、Stream、内存分配以及遇到的问题)
一、java一个文件可以写多个类吗?
1、在一个.java文件中可以有多个同级类, 其修饰符只可以public/abstract/final/和无修饰符
2、public修饰的只能有一个,且必须要与文件名相同;
3、该文件同级的类之间可以互相调用,但是除了public的类,其他不能够在其他文件调用
在一个.java文件中由类/Enum/接口/Anontation其中至少一个类型组成。
单独一个方法/变量不能独自存在与文件中,所以公用方法的封装也是做成类方法。
原因是java是类加载机制,需要编译一个java文件成多个class文件,当类来使用。
用javac 编译这个.java文件的时候,它会给每一个类生成一个.class文件
二、乱码问题,比如.properties配置文件
file——settings——editor——file encodings页面,都设置为utf-8
三、匿名函数
1、lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
2、在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量
实现步骤
1、先申明只有一个抽象方法的接口;
@FunctionalInterface // 要求接口有且只有一个抽象方法 interface Demo { int test(int a, int b); }
2、写一个函数,函数中可以写很多其他额外的操作
public static Integer handler(int a,int b,Demo demo){ return demo.test(a,b); }
3、使用函数并实现接口
int result=handler(1, 2, (z,x)->z ); System.out.println(result);
如果没有第二步,则使用方式如下,第二步相当于已经做了一部分操作。
Demo d = (int a, int b) -> a + b; int result=d.test(1,2); System.out.println(result);
java8内置的四大函数式接口
1、消费型接口, 有输入无返回
Consumer<T>:
void accept(T t)
实现例子:m-> System.out.println(m);
2、供给型接口,无输入有返回
Supplier<T>:
T get()
实现例子:()-> (int)(Math.random()*100);
3、函数型接口,有输入有返回
Function<T,R>:
R apply(T t)
实现例子:(a,b)-> a+b
4、断言型接口, 有输入返回布尔
Predicate<T>:
boolean test(T t)
实现例子:a-> a>0
四、方法引用
这个搞得我脑壳疼,还是不明白
找到的定义是这样的:
如果一个方法的调用中,这个方法给接口提供的参数和他接收的返回,和你现有某个实现完全一致,就可以进一步进行简化,称为方法引用
第二天搞明白了,看了廖雪峰的一个教程 https://www.liaoxuefeng.com/wiki/1252599548343744/1305207799545890
说实例方法有一个隐含的this
参数,在实际调用的时候,第一个隐含参数总是传入this
五、Stream
https://www.runoob.com/java/java8-streams.html
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象.
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等.
六、java内存
Java把内存分成:栈内存,堆内存,方法区,本地方法区和寄存器等。
1、栈-Stack
a、方法在栈中运行
b、存放的都是局部变量(方法的参数、方法{}中的变量),方法体中的引用变量和基本类型的变量都在栈上,其他都在堆上
2、堆-Heap
a、用来存放动态产生的数据,比如new出来的对象。
b、成员变量存储在堆,对象的引用存储在栈。
c、堆内存的东西都有地址值:16进制
d、堆内存的数据,都有默认值,如下:
整数 0
浮点数 0.0
字符 '\u0000'
布尔 false
引用类型 null
3、方法区
1、储存.class相关信息,包含方法的信息。
2、在Java虚拟机中,方法区是可供各线程共享的运行时内存区域
在.class文件加载时,静态方法和非静态方法都会加载到方法区中,只不过要调用到非静态方法时需要先实例化一个对象,
对象才能调用非静态方法。如果让类中所有的非静态方法都随着对象的实例化而建立一次,那么会大量消耗内存资源,
所以才会让所有对象共享这些非静态方法,然后用this关键字指向调用非静态方法的对象
4、本地方法栈
与操作系统有关
5、寄存器
JVM内部虚拟寄存器,存取速度非常快,程序不可控制。
常量池、静态成员变量都在堆中
JVM为每个加载的类型维护一个常量池,常量池是这个类型用到的常量的集合。
存放字符串常量和基本类型常量(public static final)
https://blog.csdn.net/weixin_39801465/article/details/114870314 加载顺序和内存存放位置 https://blog.csdn.net/weixin_43513342/article/details/85043465
https://blog.csdn.net/yuan_qh/article/details/100851544
年轻代,用来存放新近创建的对象,尺寸随堆大小的增大和减小而相应的变化,连续空间;
老年代,里面的对象几乎个个都是从年轻代熬过来的,它们是不会那么容易就 “死掉” 了的,不连续的内存空间;
永久代,存放JVM运行时使用的类,永久代同样包含了Java SE库的类和方法,永久代并不是Java堆内存的一部分。
jdk1.7中的常量池确实是移到了堆中,同时在jdk1.8中移除整个永久代,取而代之的是一个叫元空间(Metaspace)的区域