Java核心技术(高阶)

Java高阶

一、Java语法糖

  1. 概述:
  • 语法糖使程序更容易编写程序,更清晰准确表达业务逻辑
  • 语法糖不仅仅是语法的转换,也包括一些小的改进
  • 语法糖不仅仅是语法的转换,也包括一些小的改进
  1. 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 只能向前遍历,不支持向后遍历
	}
  1. 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. 语法糖不定项参数(可变参数)
  • 一个方法只能有一个不定项参数,且必须位于参数列表的最后
  • 重载的优先级规则:
  • 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);
	}
}


  1. 接口的默认方法(以default默认方法)
  • 默认方法不能重写Object中的方法
  • 实现类可以继承/重写父接口的默认方法
  • 接口可以继承/重写父接口的默认方法
  • 当父接口和父接口都有同名方法时,子类继承父类的默认方法
  • 子类实现了2个接口,那么编译失败,必须在子类重写default方法
  1. 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
	}
}
  1. 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");
	}
  1. 接口vs抽象类
  • 相同点:都是抽象的,都不能被实例化,即不能被new

  • 都可以有实现的方法

  • 都可以不需要继承者实现所有的方法

  • 不同点:抽象类最多只能继承一个,接口可以实现多个

  • 接口的默认变量是public static final,且必须有初始值,子类不能修改,而抽象类则是default,子类可以继承修改

  • 接口没有构造器,抽象类有

  • 接口没有main函数,抽象类可以有

  1. 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泛型

  1. 泛型:编写的代码可以被很多不同类型的对象所重用
//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());  
	    }
  • 泛型的本质:参数化类型,避免类型转换,代码可以重复用
  1. 自定义泛型
//泛型类:具有泛型变量的类
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;
	}
}
  1. 泛型类型限定
  • 编写的代码可以被很多不同类型的对象所重用

  • 特定场合下,需要对类型进行限定

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;
	}
}
  1. 泛型通配符类型
  • 上限界定符,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();
    }
  1. 反射的关键类
//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);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值