Java高阶
一、Java语法糖
- 概述:
- 语法糖使程序更容易编写程序,更清晰准确表达业务逻辑
- 语法糖不仅仅是语法的转换,也包括一些小的改进
- 语法糖不仅仅是语法的转换,也包括一些小的改进
- for/for-each
public static void arrayTraverse()
{
System.out.println("=========数组遍历测试==========");
double[] nums = new double[5];
for(int i=0;i<nums.length;i++)
{
nums[i] = Math.random();
}
for(double item : nums)
{
System.out.println(item);
}
}
public static void forWardOrBackwardTraverse()
{
System.out.println("=========数组正反向遍历测试==========");
double[] nums = new double[5];
for(int i=0;i<nums.length;i++)
{
nums[i] = Math.random();
}
for(int i=0;i<nums.length;i++)
{
System.out.println(nums[i]);
}
for(double item : nums)
{
System.out.println(item);
}
for(int i=nums.length-1;i>=0;i--)
{
System.out.println(nums[i]);
}
//for-each 只能向前遍历,不支持向后遍历
}
- Java的枚举类
- Java所有的enum类型都是Enum的子类,也继承了相应的方法
- 除了枚举的内容,还可以添加属性/构造方法/构造函数/方法
- 构造函数只能是package-private(default)或者private,内部调用
public class B {
enum Fruit {
APPLE(10), ORANGE(8);
private int price;
Fruit(int price) {
this.price = price;
}
public int getPrice(){
return this.price;
}
// Fruit a1=Fruit.APPLE;
}
public static void main(String[] args) {
Fruit a1=Fruit.APPLE;
System.out.println(a1.getPrice());
}
}
- 语法糖不定项参数(可变参数)
- 一个方法只能有一个不定项参数,且必须位于参数列表的最后
- 重载的优先级规则:
- 1.固定参数的方法,比可变参数优先级更高
- 2.调用语句,同时与两个带可变参数的方法匹配,则报错
//静态导入
public static void importMath() {
int a=3, b=4, c=0;
c = (int) sqrt(pow(a,2)+pow(b,2));
c = (int) Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
out.println("c is " + c);
System.out.println("c is " + c);
}
--------------------------------------------------------------------------------
public class BadImportStaticTest {
public static void main(String[] args) {
double s = PI * pow(parseDouble(args[0]),2);
NumberFormat nf = getInstance();
nf.setMaximumFractionDigits(parseInt(args[1]));
System.out.println("圆面积是:" + nf.format(s));
//System.out.println("最大值:" + MAX_VALUE); //error
System.out.println("最大值:" + Integer.MAX_VALUE);
}
}
- 接口的默认方法(以default默认方法)
- 默认方法不能重写Object中的方法
- 实现类可以继承/重写父接口的默认方法
- 接口可以继承/重写父接口的默认方法
- 当父接口和父接口都有同名方法时,子类继承父类的默认方法
- 子类实现了2个接口,那么编译失败,必须在子类重写default方法
- Java 8接口的静态方法
public interface StaticAnimal {
public static void move()
{
System.out.println("I can move");
}
}
public class StaticSwan implements StaticAnimal {
public static void main(String[] args) {
StaticAnimal.move();
StaticLandAnimal.move(); //error
new StaticSwan().move(); //error
}
}
- Java 9接口的私有方法
public interface PrivateAnimal {
public default void run()
{
move();
move2();
System.out.println("I can run");
}
public default void fly()
{
move();
System.out.println("I can fly");
}
private void move()
{
//非静态的私有方法
System.out.println("I can move");
System.out.println("I am growing");
}
public static void run2()
{
move2();
System.out.println("I can run");
}
public static void fly2()
{
move2();
System.out.println("I can fly");
}
private static void move2()
{
//静态的私有方法
System.out.println("I can move");
System.out.println("I am growing");
}
- 接口vs抽象类
-
相同点:都是抽象的,都不能被实例化,即不能被new
-
都可以有实现的方法
-
都可以不需要继承者实现所有的方法
-
不同点:抽象类最多只能继承一个,接口可以实现多个
-
接口的默认变量是public static final,且必须有初始值,子类不能修改,而抽象类则是default,子类可以继承修改
-
接口没有构造器,抽象类有
-
接口没有main函数,抽象类可以有
- var类型和switch
- var:局部变量推测,避免信息冗余,对齐了变量名,更容易阅读
int a1=5;
float a2=0.23f;
String a3="abc";
var b1=5;
var b2=0.2;
var b3="abc";
-
var的限制:可以用在局部变量上,非类成员变量
-
可以用在for/ for-each循环中,声明时必须初始化
-
不能用在方法(形式)参数和返回类型
-
大面积滥用会使代码整体阅读性变差
-
var只在编译时起作用,没有在字节码中引入新的内容,也没有专门的JVM指令处理var
-
switch
-
public static void testCharacter() { Character a = 100; switch(a) { case 100: System.out.println("100"); break; case 127: System.out.println("127"); break; default: System.out.println("0"); } } public static int judgeMonthDay(String month) { int result = 0; switch(month) { case "Jan": case "Mar": case "May": case "July": case "Aug": case "Oct": case "Dec": result = 31; break; case "Apr": case "June": case "Sep": case "Nov": result = 30; break; case "Feb": result = 28; break; default: result = -1; } return result; }
二、Java泛型
- 泛型:编写的代码可以被很多不同类型的对象所重用
//ArrayList支持泛型
//<String> 限定了list只能存放字符串
ArrayList<String> list = new ArrayList<String>();
list.add("123");
list.add("456");
list.add("789");
String a1 = list.get(1);
for(String o:list)
{
System.out.println(o);
}
//Iterator接口支持泛型
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
Iterator<Double> iter2 = set1.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
- 泛型的本质:参数化类型,避免类型转换,代码可以重复用
- 自定义泛型
//泛型类:具有泛型变量的类
public class Interval<T> {
private T lower;
private T upper;
public Interval(T lower, T upper) {
this.lower = lower;
this.upper = upper;
}
public T getLower() {
return lower;
}
public void setLower(T lower) {
this.lower = lower;
}
public T getUpper() {
return upper;
}
public void setUpper(T upper) {
this.upper = upper;
}
}
//泛型类调用:传入具体的类
public class IntegerInterval {
private int lower;
private int upper;
public IntegerInterval(int lower, int upper) {
this.lower = lower;
this.upper = upper;
}
public int getLower() {
return lower;
}
}
public class IntervalTest {
public static void main(String[] args) {
Interval<Integer> v1 = new Interval<Integer>(1,2);
int lower = v1.getLower();
int upper = v1.getUpper();
System.out.println(lower + "," + upper);
Interval<Integer> v2 = new Interval<>(1,2);
Interval<Integer> v3 = getReverse(v2);
System.out.println(v3.getLower() + "," + v3.getUpper());
}
public static <T> Interval<T> getReverse(Interval<T> interval){
return new Interval<T>(interval.getUpper(), interval.getLower());
}
}
//泛型方法
public class ArrayUtil {
public static <T> T getMiddle(T... a)
{
return a[a.length/2];
}
}
//泛型接口
public class Interval<T> {
private T lower;
private T upper;
public Interval(T lower, T upper) {
this.lower = lower;
this.upper = upper;
}
public T getLower() {
return lower;
}
public void setLower(T lower) {
this.lower = lower;
}
public T getUpper() {
return upper;
}
public void setUpper(T upper) {
this.upper = upper;
}
}
- 泛型类型限定
-
编写的代码可以被很多不同类型的对象所重用
-
特定场合下,需要对类型进行限定
public class ArrayUtil {
public static <T extends Comparable> T getMin(T... a) {
if (null == a || a.length <= 0) {
return null;
}
T min = a[0];
for (int i = 1; i < a.length; i++) {
if (min.compareTo(a[i]) > 0) {
min = a[i];
}
}
return min;
}
}
- 泛型通配符类型
- 上限界定符,Pair<?extends S>:pair能接收的参数类型,是S自身或者子类
- 只能对get/不能set,编译器只能保证出来的类型,不能保证放入的对象类型
- 下限界定符,Pair<?super A>:pair能接收的参数类型,是S自身或者超类
- 只能set/不能get,编译器保证放入的是S本身或超类,但不保证出来是什么具体类
三、Java反射
1.反射创建对象
//newInstance 调用构造函数
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Object obj=Class.forName("B").newInstance();
Method m=Class.forName("B").getMethod("he");
m.invoke(obj);
}
//newInstance 调用构造函数
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Constructor<B> constructor = B.class.getConstructor();
B obj = constructor.newInstance();
obj.he();
}
- 反射的关键类
//Filed:成员变量
public class FieldTest {}
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
A obj = new A(20, "Tom");
Class c = obj.getClass();
//获取本类及父类所有的public字段
Field[] fs = c.getFields();
System.out.println(fs[0].getName() + ":" + fs[0].get(obj));
//获取本类所有声明的字段
Field[] fs2 = c.getDeclaredFields();
for(Field f : fs2)
{
f.setAccessible(true);
System.out.println(f.getName() + ":" + f.get(obj));
}
}
}
class A
{
public int age;
private String name;
public A(int age, String name)
{
this.age = age;
this.name = name;
}
}
//Method:成员方法
public class MethodTest {
public static void main(String[] args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
B obj = new B();
Class c = obj.getClass();
// 获取public方法 包括父类和父接口
Method[] ms = c.getMethods();
for (Method m : ms) {
if ("f1".equals(m.getName())) {
m.invoke(obj, null);
}
}
// 获得该类的所有方法
Method[] ms2 = c.getDeclaredMethods();
for (Method m : ms2) {
if ("f2".equals(m.getName())) {
m.setAccessible(true);
String result = (String) m.invoke(obj, "abc");
out.println(result);
}
}
}
}
class B {
public void f1() {
out.println("B.f1()...");
}
private String f2(String s) {
out.println("B.f2()...");
return s;
}
}
//Constructor:构造函数
public class ConstructorTest {
public static void main(String[] args)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
D d = new D();
Class c = d.getClass();
Constructor[] cons = c.getConstructors();
for (Constructor con : cons) {
if (con.getParameterCount() > 0) {
// 有参构造函数
D obj = (D) con.newInstance(100);
obj.printNum();
} else {
// 无参构造函数
D obj = (D) con.newInstance();
obj.printNum();
}
}
}
}
class D {
private int num;
public D() {
this.num = 10;
}
public D(int num) {
this.num = num;
}
public void printNum() {
System.out.println(this.num);
}
}
// 父类/父接口
public class SuperTest {
public static void main(String[] args) {
Son son = new Son();
Class c = son.getClass();
Class father = c.getSuperclass();
System.out.println(father.getName());
Class[] inters = c.getInterfaces();
for(Class inter : inters)
{
System.out.println(inter.getName());
}
}
}
class Father { }
class Son extends Father
implements Cloneable, Comparable
{
protected Object clone() throws CloneNotSupportedException
{
return super.clone();
}
public int compareTo(Object o) {
return 0;
}
}
五、Java注解
import java.lang.annotation.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
//Annotation:注解
//@SuppressWarnings("all")//压制所有警告
public class AnnotationTest {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {
// int a = 5;
// Date d = new Date();
// System.out.println(d.getYear());//@Deprecated:过时的代码
String className="AnnotationTest";
for (Method m:Class.forName(className).getMethods()
) {
if (m.isAnnotationPresent(SingleTest.class)){
System.out.println(m.getName());
SingleTest st=m.getAnnotation(SingleTest.class);
m.invoke(null,st.a(),st.b());
}
}
}
@SingleTest(a=1,b=2)
public static void m1(int a,int b){
if (a+b<0)
System.out.println("Crash");
}
@SingleTest()
public static void m2(int a,int b){
if (a+b==0)
System.out.println("Push");
}
public void ha() {
}
}
class son extends AnnotationTest {
@Override//覆盖某一父类的方法
public void ha() {
System.out.println("son.ha");
}
}
//元注解:修饰注解的注解
//@Retention(保留):用来修饰其他注解的存在范围
//RetentionPolicy.SOURCE:注解不会保存到class文件中
//RetentionPolicy.CLASS:注解会保存到class文件中但是不会被JVM加载(默认方法)
//RetentionPolicy.RUNTIME:注解会保存在class文件中而且会被JVM加载,反射识别
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface SingleTest {
int a() default 0;
int b() default 0;
// String para();
}
//@Target():限定目标注解作用于什么位置
//ElementType.FILED:只能用来修饰成员变量
//ElementType.METHOD:只能用来修饰方法
//@Inherited:让一个类和他的子类都包含某个注解 注:普通的注解没有继承功能
//@Repeatable(容器注解):表示被修饰的注解可以重复应用标注,需要定义注解和容器注解
//容器注解中需要定义原注解的数组,例:
@Repeatable(RepeatableAnnotations.class)//括号中的注解即为容器注解
@interface RepeatableAnnotation{
int a() default 0;
int b() default 0;
}
@interface RepeatableAnnotations{
RepeatableAnnotation [] value();
}
//@Documented:指明这个注解可以被javadoc工具解析,形成帮助文档
六、嵌套类
//静态嵌套类:嵌套类中包含static
//非静态嵌套类(内部类):1、成员内部类 2、局部内部类 3、匿名内部类
public class NestedTest {
String name;
//静态嵌套类
static class Inner1{
String name;
}
//成员内部类
public class Inner2{
String name;
}
//局部内部类
public void f1(){
class Inner3{
String name;
}
}
//匿名内部类
public void f2(){
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
}).start();
}
}
七、Lambda表达式
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static java.lang.Math.floor;
import static java.lang.StrictMath.random;
public class Lambda {
public static void main(String[] args) {
String[] numbers = {"1", "12", "123", "1234", "12345", "1234567", "12345678"};
System.out.println("Lambda:");
//Arrays.sort(numbers,(first,second)->(first.length()-second.length()));
//形参可以不用写类型,JVM可以自动推导出来,且表达式中不能加修饰符以及返回值类型,带return语句必须加上{}
//函数式接口,只包含一个抽象方法的接口,Lambda表达式自动填充上这个方法
Comparator<String> c = (first, second) -> first.length() - second.length();
Arrays.sort(numbers, c);
System.out.println(Arrays.toString(numbers));
//系统自带的函数式接口:1、Predicate 2、Consumer 3、Supplier 4、Function
//Predicate<T>:接口中含一个test方法,接受一个参数,返回一个布尔值
Predicate<String> a = s -> (s.length() % 2 != 0);
for (String p : numbers
) {
if (a.test(p)) {
System.out.println(p);
}
}
//Consumer<T>:接口中含一个accept方法,接受一个参数,做操作,无返回
Consumer<String> b = s -> System.out.println("numbers:" + s);
for (String p : numbers
) {
b.accept(p);
}
//Supplier<T>:含一个get方法,无输入参数,返回一个数据
Supplier<String> d = () -> numbers[(int) floor(random() * 8)];
for (int i = 0; i < 5; i++) {
System.out.println(d.get());
}
//Function<T>:包含一个apply方法,接受一个参数,返回一个参数
Function<String, String> e = String::toUpperCase;
for (String p : numbers
) {
System.out.println("UPPER:" + e.apply(p));
}
//方法引用:Lambda表达式支持传递现有的类库函数
Arrays.sort(numbers, String::compareToIgnoreCase);//::表示方法引用,
System.out.println(Arrays.toString(numbers));
//静态方法(Class::staticMethod),例如Math::abs方法
//Math::abs等价于 x->Math.abs(x)
double n1 = -5.2;
double n2 = worker(Math::abs, n1);
System.out.println(n2);
}
public static double worker(NumFunction nf, double num) {
return nf.calculate(num);
}
}
interface NumFunction {
double calculate(double num);
}
八、Stream流
import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
//1、流的创建 2、流的转换 3、流的计算
//1.Collection接口的stream方法
Stream<String> as = new ArrayList<String>().stream();
Stream<String> hs = new HashSet<String>().stream();
//2.Arrays.stream将数组转化为Stream
Stream<String> B1 = Arrays.stream("a,b,c,d,e".split(","), 3, 5);
//3.利用Stream.of直接将数组转化
Stream<Integer> c1 = Stream.of(new Integer[5]);
Stream<String> c2 = Stream.of("a,b,c".split(","));
Stream<String> c3 = Stream.of("a", "b", "c");
//基本类型的流只有三种:IntStream,LongStream,DoubleStream
IntStream s1 = IntStream.of(1, 2, 3, 4, 5, 6);
s1 = Arrays.stream(new int[]{1, 2, 3});
s1 = IntStream.generate(() -> (int) (Math.random() * 100));
s1 = IntStream.range(1, 6);
IntStream s2 = IntStream.of(1, 2, 3, 4, 5);
Stream<Integer> s3 = s2.boxed();
IntStream s4 = s3.mapToInt(Integer::intValue);
//过滤filter
Stream<Integer> f1 = Stream.of(1, 2, 3);
Stream<Integer> f2 = f1.filter(n -> n > 2);
f2.forEach(System.out::println);
//去重distinct
Stream<Integer> d1 = Stream.of(1, 1, 1, 1, 2, 2, 2);
Stream<Integer> d2 = d1.distinct();
d2.forEach(System.out::println);
//排序sorted
Stream<Integer> ss1 = Stream.of(2, 3, 6, 8, 1, 9);
Stream<Integer> ss2 = ss1.sorted();
s2.forEach(System.out::println);
//转化map
Stream<Double> m1 = Stream.of(-1.5, 9.2, -6.8);
Stream<Double> m2 = m1.map(Math::abs);
m2.forEach(System.out::println);
//Optional类型
Optional<String> o1 = Optional.of(new String("abc"));
String o2 = o1.get();
System.out.println("o2=" + o2);
Optional<String> o3=Optional.of("abc");
Optional<String> o4=Optional.empty();
String str0=o4.orElse("def");
String str=null;
Optional<String> o5=Optional.ofNullable(str);//ofNullable方法,对于对象有可能为null情况下,安全创建
//流的计算
Integer[] a=new Integer[]{2,4,6,8};
Stream<Integer> si1=Stream.of(a);
long countResult=si1.count();
System.out.println("the count of si1 is"+countResult);
Stream<Integer> si2=Stream.of(a);
countResult=si2.filter(n-> n>10).count();
System.out.println("the count of si2 is"+countResult);
Stream<Integer> si3=Stream.of(1,2,3,4,6,6);
Iterator<Integer> it1=si3.filter(n ->n>2).iterator();
while (it1.hasNext()){
System.out.println(it1.next());
}
si3.filter(n-> n>3).forEach(System.out::println);
}
}