函数式接口

什么是函数式接口?

  1. 在java中'有且仅有一个抽象方法的接口',就称为函数式接口。
  2. 可以通过Lambda表达式来创建该接口的对象。(若Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)
  3. 我们可以在任意函数接口上使用@Functionallnterface 注解java8中,这样可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。
  • 备注:"语法糖"是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部类的“语法糖”,但是二者在原理上是不同的。

    • Lambda表达式的本质:作为函数式接口的实例
    • java.util.function包下定义了java8丰富的函数接口

参考地址: https://www.cnblogs.com/dgwblog/p/11739500.html#2677150870

函数类格式:

  • 只有确保接口当中有且仅有一个抽象方法
修饰符 interface 接口名称{
public abstract 返回值 方法名称(参数列表)
// 其他方式
}
// public abstract 可以不写 编译器自动加上
修饰符 interface 接口名称{
返回值 方法名称(参数列表)
// 其他方式
}

自定义函数接口

@FunctionalInterface//注解表明他是一个函数接口
interface Test {
void method();
}
public class FunctionInterfaceDemo {
public static void main(String[] args) {
//第一种
Test t = () -> {
System.out.println("zaide");
};
t.method();
//第二种
show(() -> System.out.println("你好"));
}
//定义一个方法含有接口的方法
public static void show(Test test) {
//调用里面的方法
test.method();
}
}
自定义函数接口的用途
  • 对于自定义的函数式接口,一般用于方法的参数和返回值上。

  • 函数式编程

    • 能够兼顾java的面向对象特性基础上,通过Lambda表达式上与方法引用,为开发者打开函数式编程的大门。

Lambda的延迟加载

  • 描述: 有些场景的代码运行执行后,结果不一定会被使用到,从而造成性能的浪费。而lambda表达式是延迟执行的,正好可以解决此问题,提升性能。

  • 性能浪费的日志案例

    注:日志可以帮助我们快速的定位问题,记录程序运行过程中的情况

    /**
    * showLog()方法如果传递的日志等级不是3以下的
    * 那么就不会显示拼接之后的信息
    * 所以对于程序来说,你这个日志信息的拼接动作就浪费了
    */
    public class LoggerDemo {
    //定义一个方法根据日志的等级,显示日志信息的内容
    public static void showLog(int level, String message) {
    //对日志的等级进行判断,如果日志的等级在3以下,就全部输出
    if (level <= 3) {
    System.out.println(message);
    return;
    }
    System.out.println("日志等级较高");
    } public static void main(String[] args) {
    String message1 = "执行mysql";
    String message2 = "执行java.exe";
    String message3 = "执行tomcat";
    showLog(2, message1 + message2 + message3);
    }
    }

    使用Lambda表达式优化

    /**
    * 使用lambda优化刚才的日志输出案例
    * lambda的特点,具有延迟加载
    * lambda使用前提;提供一个函数接口
    */
    public class LoggerLambdaDemo {
    //定义一个显示日志的方法,方法的参数传日志的等级和BuildLogMassage接口
    public static void showLog(int level, BuildLogMassage log) {
    //对于日志等级进行判断,如果小于3就输出
    if (level <= 3) {
    //// 实际上利用内部类 延迟的原理,代码不相关 无需进入到启动代理执行
    System.out.println(log.sendLogMassage());
    }
    }
    /*
    * 使用lambda表达式作为参数传递,
    * 只有满足条件,日志的等级小于等于3
    * 才会调用此接口BuildLogMassage种的方法
    * 才会调用字符串的拼接
    * 如果条件不满足,日志的等级大于3
    * 那么BuildLogMassage接口种的方法与不会执行
    * 所以拼接字符串的动作也不会执行
    * 所以不会存在性能上的浪费。
    **/
    public static void main(String[] args) {
    String message1 = "执行mysql";
    String message2 = "执行java.exe";
    String message3 = "执行tomcat";
    //调用showLog方法,参数是一个函数接口,可以使用lambda表达式
    showLog(5, () -> {
    //返回一个拼接好的字符串
    //System.out.println("前面的日志等级大于3此处不执行");//没有输出
    return message1 + message2 + message3;
    });
    }
    } @FunctionalInterface
    interface BuildLogMassage {
    //定义有且只有一个抽象方法,拼接日志信息
    String sendLogMassage();
    }
    //备注;实际上使用内部类也可以达到这样的操作,只是将代码操作延迟到另外一个对象当中通过调用方法来完成。后面的代码执行取决于前面的条件的判断的结果。

    备注:SLF4J是应用非常广泛的日志框架,它在记录日志时为了解决这种性能浪费的问题,并不推荐首先进行字符串的拼接,而是将字符串的若干部分作为可变参数(包装为数组)传入方法中,仅在日志级别满足要求的情况下才会进行字符串拼接。

使用Lambda作为方法的参数和返回值

  • 参数

    在Java当中,lambda表达式是作为匿名内部类的替代品,如果一个方法的参数一个函数式接口类型,那么可以使用lambda表达式进行替代。
    java.lang.Runnable接口就是一个函数式接口
  • 代码演示

    public class Demo {
    //定义一个方法,开启线程
    public static void startThread(Runnable r) {
    new Thread(r).start();
    }
    public static void main(String[] args) {
    startThread(() -> {
    System.out.println("线程任务--》线程任务被执行了");
    });
    //优化
    startThread(() ->
    System.out.println("线程任务--》线程任务被执行了")
    );
    }
    }
  • 返回值

    如果一个方法的返回值类型是一个函数式接口,那么我们可以直接使用一个lambda表达式
    java.util.Comparator 接口是一个函数式接口
  • 代码演示

    public class Demo2 {
    //定义一个方法,方法的返回值类型是一个函数式接口类型Comparator
    public static Comparator<String> createCoparator() {
    //返回值就是一个函数式接口
    /* return new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
    //自定义比较的规则 升序/降序
    //字符串的长度
    return o1.length() - o2.length();
    }
    };*/
    //使用lambda表达式使用 字符串长度升序
    /* return (o1, o2) ->
    o1.length() - o2.length();*/
    return Comparator.comparingInt(String::length); }
    public static void main(String[] args) {
    String [] str={"ddd","aa","zz","qqqq","pppp"};
    Arrays.sort(str,createCoparator());
    System.out.println(Arrays.toString(str));
    }
    }

常用的函数式接口

  • 常用接口

  • jdk提供了大量常用的函数式接口,丰富lambda表达式的使用场景。他们主要在java.uiil.function包下。

Supplier<T>(供应接口)

描述

  • java.util.function.Supplier 接口,该接口有且仅有一个无参的方法;

  • 方法: T get(); 用来获取一个泛型参数指定类型的对象,由于这是一个函数接口,这就意味就可以使用Lambda表达式。需要对外提供一个符合泛型类型的对象数据。

  • Supplier<T>接口称为生产型接口,指定接口的泛型是什么类型,那么接口种的get()方法就会生产什么类型的数据。

public class SupplierDemo {
//定义一个方法,方法的参数传递一个Supplier<T>接口
//泛型指定String,get方法就会返回一个String
public static String getString(Supplier<String> sup) {
return sup.get();
} //定义一个方法,方法的参数传递一个Supplier<T>接口
//泛型指定位Integer,get方法就会返回一个int
public static Integer getNum(Supplier<Integer> sup) {
return sup.get();
} public static void main(String[] args) {
//调用getString方法,方法的参数传递supplier<T>是一个
//函数接口,那么我们就可以使用lambda
/* String s = getString(() -> {
return "你好java";
});
System.out.println(s);*/ //求一个int类型的数组种的最值
int[] arr = {10, 23, 4, 76, 98, 2};
Integer Max = getNum(() -> {
//求出数组的最大值
int max = arr[0];
for (int i : arr) {
//判断
if (max < i) {
max = i;
}
}
return max;
});
//输出最大值
System.out.println(Max);
}
}

Consumer<T>消费型接口

  • 描述

    	java.util.funciton.Consumer<T> 接口刚好和Supplier接口相反,他不是用来生产一个数据,而是消费一个数据。
    数据的类型有泛型来指定。
    void accept(T t);
    其中方法accept;意思就是消费一个指定的类型的数据
  • 代码实例

    public class ConsumerDemo {
    //定义一个方法,方法的参数传递一个Consumer<T>接口,传递一个字符串
    public static void Consumer(String str, Consumer<String> con) {
    con.accept(str);
    }
    public static void main(String[] args) {
    //来调用消费方法Consumer,
    //Consumer<String>接口是一个函数式接口类型,所以可以使用lambda
    Consumer("China", (name) -> {//name是将你传入的那个数据起个名字
    //把里面的字符转换为大写
    String s = name.toUpperCase();//转换大写
    String str = new StringBuffer(s).reverse().toString();//反转
    System.out.println(str);
    });
    }
    }

Consumer的默认方法

 andThen' //于是呐/然后
如果一个方法的参数和返回值全都是Consumer类型,那么就可以实现这样的效果;'消费数据的时候,首先做一个消费的操作,在做一个消费的操作'。实现组合。可以通过Consumer接口总的默认方法;'andThen'来实现
  • 代码如下
public class ConsumerAndThenDemo {
//定义一个方法,方法参数传递一个字符串,和两个Consumer接口
//Consumer这个接口的泛指定为字符串
public static void consumer(String str, Consumer<String> con1, Consumer<String> con2) {
/* con1.accept(str);
con2.accept(str);*/
//andThen 连续消费
//先执行左边的Consumer--con1的动作,andThen-->再次执行Consumer--> con2动作
con1.andThen(con2).accept(str);
//消费规则;con1连接con2,先执行con1消费数据,在执行con2消费数据
} public static void main(String[] args) {
//由于consumer方法的参数Consumer接口是一个函数接口所以使用lambda
consumer("java31-都是-大佬", (name1) -> {
//消费规则
//截取传入的字符串
String s = name1.substring(0, 6);
System.out.println(s); }, (name2) -> {
//定义消费的规则,分成字符串数组展示
String[] strs = name2.split("-");
System.out.println(Arrays.toString(strs));
});
}
}
//通过查看源码的知,andThen方法不允许传入一个null对象否则就抛出一个空指针
'想要把两次消费的动作连接起来,需要传入两个Consumer接口,通过andThen方法实现一步一步的执行消费动作'
  • 练习;定义一个字符串数组,存储每一个人的信息如;张三,20,郑州市,存储5个人的信息,使用consumer接口,按照指定的格式打印输入;姓名;张三;年龄;20;地址;郑州市,要求打印姓名动作为第一个consumer接口的规则,将打印年龄的动作为第二个consumer接口的规则,将打印地址的动作为第三个consumer接口的规则。最终将三个consumer接口按照规定的顺序拼接出来。antThen

    public class Test {
    public static void show(People[] people, Consumer<People> c1, Consumer<People> c2, Consumer<People> c3) {
    //循环遍历依此拿到个是一个人信息
    for (People p : people) {
    //先拿到的先执行
    c1.andThen(c2).andThen(c3).accept(p);
    }
    } public static void main(String[] args) {
    People[] p = {new People("古力娜扎", 20, "新疆"),
    new People("迪丽热巴", 25, "齐齐哈尔"),
    new People("马儿扎哈", 19, "内蒙")};
    //调用方法使用lambda表达式进行使用
    show(p, (c1) -> {
    System.out.print(c1.getName()+" ");
    },
    (c2) -> {
    System.out.print(c2.getAge()+" ");
    }
    , (c3) -> {
    System.out.println(c3.getCity()+" ");
    });
    } }
    //用一个类来表示
    class People {
    private String name;
    private int age;
    private String city; public People() {}
    @Override
    public String toString() {
    return "People{" +
    "name='" + name + '\'' +
    ", age=" + age +
    ", city='" + city + '\'' +
    '}';
    } public String getName() {return name;} public void setName(String name) {this.name = name;} public int getAge() {return age;} public void setAge(int age) {this.age = age;} public String getCity() { return city;} public void setCity(String city) {this.city = city;} public People(String name, int age, String city) {this.name = name;this.age = age;this.city = city;}
    }

Predicate<T> 断言接口

  • 描述
    java.util.Predicate 函数式接口。其中唯一的抽象方法。
    boolean test(T t);该方法返回布尔类型值,代表指定的条件满足返回true,
    那么Stream的方法filter将其中的元素保留下来,如果条件不满足返回false,
    那么filter方法会舍弃该元素。
  • 练习
        @Test
    public void test4() {
    ArrayList<String> list = new ArrayList<>();
    list.add("java");
    list.add("pht");
    list.add("python");
    list.add("go");
    list.add("linux");
    List strList = filtrate(list, (e) ->
    e.length() > 3
    );
    //stream 流
    strList.forEach(System.out::println);
    } //需求:将满足的字符串,放入集合中
    public List filtrate(ArrayList<String> arrayList, Predicate<String> pr) {
    ArrayList<String> list = new ArrayList<>();
    for (String s : arrayList) {
    if (pr.test(s)) {
    list.add(s);
    }
    }
    return list;
    }

Function<T, R> 函数接口

  • 描述

    java.util.stream.Function 函数式接口。其中唯一的抽象方法:
    R apply(T t); (接口本身接口两个数据T/R,方法返回一个数据R)
    //可以将一种类型T类型的数据转换成R类型的数据,那么这种转换的动作,我们称之为”映射“
  • 练习

        @Test
    public void test5() {
    String strHander = strHander("\t\t\t过的不错的小日本 ", (str) ->
    str.trim()
    );
    System.out.println(strHander);
    } //需求:用来处理字符串
    public String strHander(String str, Function<String, String> fu) {
    return fu.apply(str);
    }

方法引用构造器引用(基于lambda)

方法引用(Method References)

	1.当要传递给Lambda体的操作,已有实现的方法了,可以使用方法引用!
2.方法引用可以看作是Lambda表达深层的表达。换句话说,方法引用就是lambda表达式,也就是函数接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
3.要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
4.格式:(或对象)'::'方法名。
5.如下三种主要使用情况:
对象::实例方法名
类::静态方法名
类::实例方法名
//注意;当函数式接口方法的第一个参数是需要引用方法的调用者,并且第二个参数是需要引用方法
//的参数(或者无参数)时:ClassName::methodName

构造器引用

格式:ClassName::new
与函数接口相结合,自动与函数式接口中方法兼容。
可以把构造器引用赋值给定义的方法,要求构造器参数列表与接口中抽象方法的参数列表一致!且方法的返回值即为构造器对应类的对象。

数组引用

格式: type[] :: new
  • 为什么这样写

    推到与省略
    如果使用Lambda,那么根据'可推到可以省略原则',无序指定参数类型,无需指定的重写的形式 --》它们都可以被堆到出来,所以就可以省略掉。我们能够使用方法引用,同样也是根据上下文进行推导。
    函数式接口是lambda的基础,而方法引用是lambda的优化品。

代码练习

通过对象引用实例方法

@FunctionalInterface
public interface Printable {
// 定义唯一的抽象方法
void print(String str);
}
public class MthodTest2 {
//定义一个方法成员方法,传递一个字符串,把字符串改为大写输出
public void pringUpperCaseString(String str){
System.out.println(str.toUpperCase());
}
}
public class MethodTest {
// 定义一个静态的方法,方法的参数传递一个函数式接口
public static void pringString(Printable p) {
p.print("hello word");
} public static void main(String[] args) {
// 传统的lambda表达式写法
pringString((String str) -> {
System.out.println(str.toUpperCase());//
/*
* MthodTest2 test2 = new MthodTest2();
* test2.pringUpperCaseString(str);//传值的动作 通过对象调用方法
*/ });
//打印流对象已经确定
PrintStream ps = System.out;
//通过对象引用对应的成员方法
pringString(ps::println); /**
* 使用方法引用优化lambda
* 1.对象必须是已经存在的
* 2.成员方法也是已经存在的pringUpperCaseString
* 所以我们就可以使用对象名来来引用我们成员方法
*/
// 首先必须是对象已经存在
MthodTest2 test2 = new MthodTest2();
pringString(test2::pringUpperCaseString);
}
}
//在测试类中,定义一个静态方法,静态方法传递一个函数式接口Pringtable,函数式接口当中定义了唯一 -- 抽象方法print,这个print方法接收一个字符串参数,目的就是为了打印接收的字符串参数。通常我们可以使用lambda表达式来实现以上需求,但是经过我们观察,对字符串进行控制台打印输出的操作方案,明明已经有了现成的执行方案中,System.out对象中有一个方法println(String str),所以我们可以直接通过对象名来引用该方法println来实现再控制台打印输出内容。
'打印流对象已经确定'
'PrintStream ps = System.out;'
'通过对象引用对应的成员方法'
'pringString(ps::println);'
//注意:其中的双冒号::写法,被称为方法引用

通过类名引用静态方法

//定义一个函数式接口
@FunctionalInterface
public interface MathStaticMethodDemo {
// 定义一个静态的方法
double calculateAbs(double d);}
//定义一个测试类
public class MethodStaticDemo {
// 定义一个静态方法,该方法中传递一个函数式接口
public static double calc(double d, MathStaticMethodDemo math) {
return math.calculateAbs(d);
} public static void main(String[] args) {
// 传统的lambda
double num = calc(-3.14, (d) -> {
return Math.abs(d);
});
System.out.println(num); /*
* 使用方法引用进行优化lambda
* 首先类名已经确定的
* 类中定义的静态方法是已经确定的
* 使用类名引用类中的静态方法
*/
double d = calc(-3.14, Math::abs);
System.out.println(d);
}}
//备注:lambda表达式写法: d->Math.abs(d);
方法引用写法; Math::abs; 这两种写法是等价的

通过super来引用成员方法

//定义一个父类
public class Animal {
//定义一个成员方法 交流方法
public void talk(){
System.out.println("HELLO 我是一个动物");
}
}
@FunctionalInterface
public interface Meet {
//定义一个抽象方法 見面的抽象方法
abstract void meet();
} //定义一个子类
public class Cat extends Animal {
//重写父类的方法
@Override
public void talk() {
System.out.println("HELLO 我是一直肥貓"); }
//
public void meet(Meet m) {
m.meet();
} // 定義一個成員方法 溝通
public void commun() {
//傳統的lambda表達式
meet(()->{
//創建父類對象
//調用父類的方法
Animal animal = new Animal();
animal.talk();
});
//使用父類當中的方法 直接用super來調用
meet(()->{
super.talk();
});
/**
* 使用super关键字来引用成员方法
* super已经存在
* 父类当中的成员方法talk已经存在
* 可以直接使用super引用父类当中的成员方法
*/
meet(super::talk);
} public static void main(String[] args) {
new Cat().commun();
}
}

通过this

  • 通过 thsi来引用本类当中的成员方法 this 指代当前对象,如果需要引用的方法就是本类当中的成员方法,那么可以使用 this::成员方法
@FunctionalInterface
public interface Study {
// 定义一个学习的抽象方法
void study();
} //定义一个学上类
public class Student {
//定义一个成员方法,方法的参数传递一个函数式接口study
public void study(Study study){
study.study();
}
//定义一个work方法
public void work(){
System.out.println("我今天很开心呢,因为我今天学习了");
} //定义一个成员方法快乐的方法
public void toHapy(){
//传统的lambda表达式
study(()->{
new Student().work(); });
//使用this关键字优化lambda
study(this::work);
}
public static void main(String[] args) {
new Student().toHapy();
}
}

构造器引用

public class Person {
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Person(String name) {this.name = name;}
public Person() {}//省略set get toStrig 无参 有参
}
//定义一个函数式接口
@FunctionalInterface
public interface PersonCreate {
// 定义一个抽象方法
Person createPerson(String name);
}
public class Test {// 测试类
// 定义一个方法传入一个函数式接口PersonCreate在传入一个字符串name
private static void printPersonName(String name, PersonCreate create) {
System.out.println(create.createPerson(name).getName());
}
public static void main(String[] args) {
// 使用传统的方式lambda表达式
printPersonName("王蛋", name -> new Person(name));
// 使用构造器引用lambda表达式
printPersonName("王蛋", Person::new);
/**
* lambda表达式 name->new Person(name)
* 方法引用 Person::new
*/
}
}

数组构造器引用

//定义一个函数式接口
@FunctionalInterface
public interface BuilderArrays {
// 定义唯一的抽象方法
int[] buildArrays(int length);
}
//测试类
public class Test {
// 定义一个方法方法中传递一个函数式接口,还要传递一个数组的长度
public static int[] initArrays(int length, BuilderArrays builderArrays) {
return builderArrays.buildArrays(length);
}
public static void main(String[] args) {
//先使用lambda表达式来写
int[] arr1 = initArrays(10, length->{
return new int[length];
});
System.out.println(arr1.length); //数组构造器引用优化lambda表达式
int[] arr = initArrays(10, int[]::new);
System.out.println(arr.length);
/**
* lambda表达式 length -> new int [length]
* 方法引用 int[]::new
* 这两种写法是等价的
*/
}
}

Lambda函数接口和方法构造器应用的更多相关文章

  1. Java8函数式接口/Lambda表达式/接口默认方法/接口静态方法/接口冲突方法重写/lambda表达式指定泛型类型等

    一:函数式接口 1.函数式接口的概念就是此接口必须有且只能有一个抽象方法,可以通过@FunctionalInterface来显示规定(类似@Override),但是没有此注解的但是只有一个抽象方法的接 ...

  2. [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

    函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...

  3. java8函数式接口详解、函数接口详解、lambda表达式匿名函数、方法引用使用含义、函数式接口实例、如何定义函数式接口

    函数式接口详细定义 函数式接口只有一个抽象方法 由于default方法有一个实现,所以他们不是抽象的. 如果一个接口定义了一个抽象方法,而他恰好覆盖了Object的public方法,仍旧不算做接口的抽 ...

  4. 还看不懂同事的代码?Lambda 表达式、函数接口了解一下

    当前时间:2019年 11月 11日,距离 JDK 14 发布时间(2020年3月17日)还有多少天? // 距离JDK 14 发布还有多少天? LocalDate jdk14 = LocalDate ...

  5. 009-jdk1.8版本新特性一-展方法,Lambda表达式,函数式接口、方法引用构造引用

    一.JDK1.8 名称:Spider(蜘蛛) 发布日期:2014-03-18 新特性: 1.1.扩展方法[接口的默认方法] Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 defaul ...

  6. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  7. 使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测

    概述 单测是提升软件质量的有力手段.然而,由于编程语言上的支持不力,以及一些不好的编程习惯,导致编写单测很困难. 最容易理解最容易编写的单测,莫过于独立函数的单测.所谓独立函数,就是只依赖于传入的参数 ...

  8. 使用函数接口和枚举实现配置式编程(Java与Scala实现)

    概述 做报表时,有时需要根据不同的业务生成不同的报表.这样,需要能够动态地配置列字段,并根据列字段来输出对应的报表.使用函数接口结合枚举可以比较优雅地实现配置式编程. 问题描述如下: 假设有对象 St ...

  9. 开始Java8之旅(四) --四大函数接口

    前言   Java8中函数接口有很多,大概有几十个吧,具体究竟是多少我也数不清,所以一开始看的时候感觉一脸懵逼,不过其实根本没那么复杂,毕竟不应该也没必要把一个东西设计的很复杂. 几个单词   在学习 ...

随机推荐

  1. 【Android面试查漏补缺】之Handler详解,带你全面理解Handler消息机制

    在安卓面试中,关于 Handler 的问题是必备的,但是这些关于 Handler 的知识点你都知道吗? 一.题目层次 Handler 的基本原理 子线程中怎么使用 Handler MessageQue ...

  2. 终于有人把Android技术面试知识体系整理出来了,这些学习手册让你的面试稳如泰山

    前言 年年寒冬,年年也挡不住一个安卓程序员追求大厂的决心.想要进入大厂,我们需要掌握哪些知识点呢?这里,我为大家梳理了一个整体的知识架构.整体包括Java.Android.算法.计算机基础等等,相应的 ...

  3. Git常见的操作及命令

    Git的下载安装 安装直接去Git官方网站https://git-scm.com/下载后安装即可. Git常用命令 git init初始化本地仓库(没有仓库就创建) git clone克隆远程仓库到本 ...

  4. net Entityframerwork+sqlite 数据库迁移配置(采坑日记)

    1首先在app.config配置写入add 1:<provider invariantName="System.Data.SQLite.EF6" type="Sys ...

  5. 计算机网络 中国大学MOOC 哈尔滨工业大学 习题答案

    转自 https://blog.csdn.net/qq_37514135/article/details/82733651 计算机网络作业题 第一章 第一题 如图所示网络.A在t=0时刻开始向C发送一 ...

  6. Thymeleaf页面静态化技术

    Teymeleaf的使用 案例一:springboot搭建Thymeleaf 1.导入依赖 2.新建html页面模板 3.新建前端控制层Controller 4.新建启动类 1.导入依赖 <?x ...

  7. 关于 phpstudy环境下在MySQL中执行into outfile无法导入导出文件解决方法

    之前在做sqli-labs练习,需要用到into outfile 出现以下问题: 执行SQL语句后在指定的路径下无文件生成. 例如: 执行 select into outfile "C:\\ ...

  8. XSS之防御与绕过

    很久之前的随笔讲过XSS的编码绕过的一些内容 本次侧重整理一下常见的防御思路,顺便补充一些针对性的绕过思路以及关于XSS个人想到的一些有趣的事情 开篇之前,先看一下XSS介绍(包括mXSS.uXSS. ...

  9. IP网络地址的计算

    IP地址与子网掩码进行"与"运算,得到网络地址

  10. 题解 math

    传送门 赛时用一个奇怪的方法过掉了 首先\(b_i\)的有效范围是\([0, k-1]\) 发现不同的\(a_i*b_i\)会有很多重的 考虑把\(a_i\%k\),然后由小到大排序 按顺序扫,如果某 ...