首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,509 阅读
2
Nacos持久化MySQL问题-解决方案
958 阅读
3
Docker搭建Typecho博客
762 阅读
4
滑动时间窗口算法
746 阅读
5
Nginx反向代理微服务配置
715 阅读
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
RabbitMQ
lambda
stream
少年
累计撰写
189
篇文章
累计收到
24
条评论
首页
栏目
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
页面
关于
友链
搜索到
45
篇与
的结果
2022-03-08
JAVA面向对象有那些特征
JAVA面向对象有那些特征?面向对象编程是利用类和对象编程的一种思想。万物可归类,类是对于世界事物的高度抽象,不同的事物之间有不同的关系,一个类自身与外界的封装关系,一个父类和子类的继承关系,一个类和多个类的多态关系。万物皆对象,对象是具体的世界事物,面向对象的三大特征封装,继承,多态。封装,封装说明一个类行为和属性与其他类的关系,低耦合,高内聚;继承是父类和子类的关系,多态说的是类与类的关系。封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。属性的封装:使用者只能通过事先定制好的方法来访问数据,可以方便地加入逻辑控制,限制对属性的不合理操作;方法的封装:使用者按照既定的方式调用方法,不必关心方法的内部实现,便于使用;便于修改,增强代码的可维护性;继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。在本质上是特殊~一般的关系,即常说的is-a关系。子类继承父类,表明子类是一种特殊的父类,并且具有父类所不具有的一些属性或方法。从多种实现类中抽象出一个基类,使其具备多种实现类的共同特性,当实现类用extends关键字继承了基类(父类)后,实现类就具备了这些相同的属性。继承的类叫做子类(派生类或者超类),被继承的类叫做父类(或者基类)。比如从猫类、狗类、虎类中可以抽象出一个动物类,具有和猫、狗、虎类的共同特性(吃、跑、叫等)。Java通过extends关键字来实现继承,父类中通过private定义的变量和方法不会被继承,不能在子类中直接操作父类通过private定义的变量以及方法。继承避免了对一般类和特殊类之间共同特征进行的重复描述,通过继承可以清晰地表达每一项共同特征所适应的概念范围,在一般类中定义的属性和操作适应于这个类本身以及它以下的每一层特殊类的全部对象。运用继承原则使得系统模型比较简练也比较清晰。相比于封装和继承,Java多态是三大特性中比较难的一个,封装和继承最后归结于多态,多态指的是类和类的关系,两个类由继承关系,存在有方法的重写,故而可以在调用时有父类引用指向子类对象。多态必备三个要素:继承,重写,父类引用指向子类对象。继承、封装:增强了代码的可复用性,多态:增加了可移植性、健壮性、灵活性。
2022年03月08日
183 阅读
0 评论
1 点赞
2022-03-08
ArrayList和LinkedList的区别
ArrayList和LinkedList都实现了List接口,他们有以下的不同点:ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。LinkedListt比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。也可以参考ArrayList vs.LinkedList。1)因为Array是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。Array 获取数据的时间复杂度是O(1),但是要删除数据却是开销很大的,因为这需要重排数组中的所有数据。2)相对于Arraylist,LinkedList插入是更快的。因为LinkedList不像ArrayList一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。ArrayList 在插入数据时还需要更新索引(除了插入数组的尾部)。3)类似于插入数据,删除数据时,LinkedList 也优于Arraylist。4)LinkedList 需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置(一个LinkedList实例存储了两个值:Nodefirst和Nodelast分别表示链表的其实节点和尾节点,每个Node 实例存储了三个值:Eitem,Node next,Node pre)。什么场景下更适宜使用LinkedList,而不用ArrayList1)你的应用不会随机访问数据。因为如果你需要LinkedList中的第n个元素的时候,你需要从第一个元素顺序数到第n个数据,然后读取数据。2)你的应用更多的插入和删除元素,更少的读取数据。因为插入和删除元素不涉及重排数据,所以它要比ArrayList要快。
2022年03月08日
145 阅读
0 评论
1 点赞
2022-03-08
JAVA中抽象类和接口有什么区别
JAVA中抽象类和接口有什么区别?相同:1.不能够实例化2.可以将抽象类和接口类型作为引用类型3.一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类不同:抽象类:1.抽象类中可以定义构造器2.可以有抽象方法和具体方法3.接口中的成员全都是public的4.抽象类中可以定义成员变量5.有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法6.抽象类中可以包含静态方法7.一个类只能继承一个抽象类接口:1.接口中不能定义构造器2.方法全部都是抽象方法3.抽象类中的成员可以是private、默认、protected、public4.接口中定义的成员变量实际上都是常量5.接口中不能有静态方法6.一个类可以实现多个接口
2022年03月08日
147 阅读
0 评论
1 点赞
2022-03-07
JDK1.8新特性
JDK1.8的新特性一、接口的默认方法Java8允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字即可,这个特征又叫做扩展方法,示例如下:代码如下:interface Formula{ double calculate(int a); default double sqrt(int a){ return Math.sqrt(a); } }Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用。代码如下:Formula formula=new Formula){@Override public double calculate(int a){return sqrt(a100);}];formula.calculate(100);/100.0 formula.sqrt(16);//4.0文中的formula被实现为一个匿名类的实例,该代码非常容易理解,6行代码实现了计算sqrt(a*100)。在下一节中,我们将会看到实现单方法接口的更简单的做法。译者注:在Java中只有单继承,如果要让一个类赋予新的特性,通常是使用接口来实现,在C++中支持多继承,允许一个子类同时具有多个父类的接口与功能,在其他语言中,让一个类同时具有其他的可复用代码的方法叫做mixin。新的Java8的这个特新在编译器实现的角度上来说更加接近Scala的trait。在C#中也有名为扩展方法的概念,允许给已存在的类型扩展方法,Java8的这个在语义上有差别。二、Lambda表达式首先看看在老版本的Java中是如何排列字符串的:代码如下:List names=Arrays.asList("peterF","anna","mike","xenia");Collections.sort(names,new Comparator){@Override public int compare(String a,String b){return b.compareTo(a);}});只需要给静态方法Collections.sort传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort方法。在Java8中你就没必要使用这种传统的匿名对象的方式了,Java8提供了更简洁的语法,lambda表达式:代码如下:Collections.sort(names,(String a,String b)->{return b.compareTo(a);});看到了吧,代码变得更段且更具有可读性,但是实际上还可以写得更短:代码如下:Collections.sort(names,(String a,String b)->b.compareTo(a);对于函数体只有一行代码的,你可以去掉大括号0以及return关键字,但是你还可以写得更短点:代码如下:Collections.sort(names,(a,b)>b.compareTo(a);Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型。接下来我们看看lambda表达式还能作出什么更方便的东西来:三、函数式接口Lambda表达式是如何在java的类型系统中表示的呢?每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为默认方法不算抽象方法,所以你也可以给你的函数式接口添加默认方法。我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加@Functionallnterface注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。示例如下:代码如下:@Functionallnterface interface Converter<F,T>{T convert(F from);}Converter<String,Integer>converter=from)->Integer.valueOf(from);Integer converted=converter.convert("123");System.out.printin(converted);//123需要注意如果@Functionallnterface如果没有指定,上面的代码也是对的。译者注将lambda表达式映射到一个单方法的接口上,这种做法在Java8之前就有别的语言实现,比如Rhino JavaScript解释器,如果一个函数参数接收一个单方法的接口而你传递的是一个function,Rhino 解释器会自动做一个单接口的实例到function的适配器,典型的应用场景有 org.w3c.dom.events.EventTarget的addEventListener 第二个参数EventListener。四、方法与构造函数引用前一节中的代码还可以通过静态方法引用来表示:代码如下:Converter<String,Integer>converter=Integer:valueOf;Integer converted=converter.convert("123");System.out.printin(converted);//123Java8允许你使用:关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:代码如下:converter=something::startsWith;String converted=converter.convert("Java");System.out.printin(converted);//"接下来看看构造函数是如何使用:关键字来引用的,首先我们定义一个包含多个构造函数的简单类:代码如下:代码如下:Converter<String,Integer> converter=Integer::valueOf;Integer converted=converter.convert("123");System.out.println(converted);//123Java8允许你使用::关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:代码如下:converter=something:startsWith;String converted=converter.convert("Java");system.out.println(converted);/∥"y"接下来看看构造函数是如何使用:关键字来引用的,首先我们定义一个包含多个构造函数的简单类:代码如下:class Person{String firstName;String lastName;Person)}Person(String firstName,String lastName){this.firstName =firstName;this.lastName=lastName;}}接下来我们指定一个用来创建Person对象的对象工厂接口:代码如下:interface PersonFactory{P create(String firstName,String lastName);}这里我们使用构造函数引用来将他们关联起来,而不是实现一个完整的工厂:代码如下:PersonFactorypersonFactory=Person::new;Person person=personFactory.create("Peter","Parker");我们只需要使用Person::new来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。五、Lambda作用域在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。六、访问局部变量我们可以直接在lambda表达式中访问外层的局部变量:代码如下:final int num=1;Converter<Integer,String>stringConverter=(from)->String.valueof(from +num);stringConverter.convert(2);//3但是和匿名对象不同的是,这里的变量num可以不用声明为final,该代码同样正确:代码如下:int num=1;Converter<Integer,String>stringConverter=(from)->String.valueof(from+num);stringConverter.conver(2);//3不过这里的num必须不可被后面的代码修改(即隐性的具有fina的语义),例如下面的就无法编译:代码如下:int num=1;Converter<Integer,String>stringConverter =(from)->string.valueof(from +num);num=3;在lambda表达式中试图修改num同样是不允许的。七、访问对象字段与静态变量和本地变量不同的是,lambda内部对于实例的字段以及静态变量是即可读又可写。该行为和匿名对象是一致的:代码如下:class Lambda4{static int outerStaticNum;int outerNum;void testScopes(){Converter<Integer,String>stringConverter1=(from)->{outerNum=23;return String.valueof(from);};Converter<Integer,String>stringConverter2=(from)->{outerStaticNum=72;return String.valueof(from);};}}八、访问接口的默认方法还记得第一节中的formula例子么,接口Formula定义了一个默认方法sqrt可以直接被formula的实例包括匿名对象访问到,但是在lambda表达式中这个是不行的。Lambda表达式中是无法访问到默认方法的,以下代码将无法编译:代码如下:Formula formula=(a)->sqrt(a*100);Built-in Functional InterfacesJDK 1.8API包含了很多内建的函数式接口,在老Java中常用到的比如Comparator或者Runnable接口,这些接口都增加了@Functionallnterface注解以便能用在lambda上。Java8APl同样还提供了很多全新的函数式接口来让工作更加方便,有一些接口是来自Google Guava库里的,即便你对这些很熟悉了,还是有必要看看这些是如何扩展到lambda上使用的。Predicate接口Predicate 接口只有一个参数,返回boolean类型。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非):代码如下:Predicatepredicate=(s)->s.length()>0;predicate.test("foo");//true predicate.negate().test("foo");//false Predicate nonNull =Objects:nonNull;PredicateisNull=Objects:isNull;PredicateisEmpty=String:isEmpty;PredicateisNotEmpty=isEmpty.negate();Function接口Function 接口有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose,andThen):代码如下:Function<String,Integer> tolnteger=Integer:valueOf;Function<String,String>backToString=tolnteger.andThen(String:valueOf);backToString.apply("123");//"123"Supplier 接口Supplier 接口返回一个任意范型的值,和Function接口不同的是该接口没有任何参数代码如下:Supplier personSupplier=Person:new;personSupplier get();//new PersonConsumer 接口Consumer接口表示执行在单个参数上的操作。代码如下:Consumergreeter=(p)->System.out.println("Hello,"+p.firstName);greeter.accept(new Person("Luke","Skywalker"));Comparator 接口Comparator是老ava中的经典接口,Java8在此之上添加了多种默认方法:代码如下:Comparatorcomparator =(p1,p2)->p1.firstName.compareTo(p2.firstName);Person p1=new Person("John","Doe");Person p2=new Person("Alice","Wonderland");comparator.compare(p1,p2);//>0 comparator.reversed().compare(p1,p2);//<0optional接口Optional 不是函数是接口,这是个用来防止NullPointerException异常的辅助类型,这是下一届中将要用到的重要概念,现在先简单的看看这个接口能干什么:Optional被定义为一个简单的容器,其值可能是null或者不是null。在Java8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java8中,不推荐你返回null而是返回Optional。代码如下:Optionaloptional=Optional.of("bam");optional.isPresent();//true optional.get();//"bam"optional.orElse("fallback");//"bam"optional.ifPresent((s)->System.out.println(s.charAt(O));//"b"Stream接口java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如java.util.Collection的子类,List或者Set,Map不支持。Stream的操作可以串行执行或者并行执行。首先看看Stream是怎么用,首先创建实例代码的用到的数据List:代码如下:List stringCollection=new ArrayList<>();;stringCollection.add("ddd2");stringCollection.add("aaa2");stringCollection.add("bbb1");stringCollection.add("aaa1");stringCollection.add("bbb3");stringCollection.add("ccc");stringCollection.add("bbb2");stringCollection.add("ddd1");Java 8扩展了集合类,可以通过Collection.stream()或者Collection.parallelStream()来创建一个Stream。下面几节将详细解释常用的Stream操作:Filter 过滤过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作。代码如下:stringCollection.stream().filter(s)->s.startsWith("a").forEach(System.out::println);//"aaa2","aaal"Sort 排序排序是一个中间操作,返回的是排序好后的Stream。如果你不指定一个自定义的Comparator则会使用默认排序。代码如下:stringCollection.stream().sorted().filter(s)->s.startsWith("a")).forEach(System.out:printin);//"aaa1","aaa2"需要注意的是,排序只创建了一个排列好后的Stream,而不会影响原有的数据源,排序之后原数据stringCollection是不会被修改的:代码如下:System.out.printin(stringCollection);//ddd2,aaa2,bbb1,aaal,bbb3,ccc,bbb2,ddd1Map映射中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象,下面的示例展示了将字符串转换为大写字符串。你也可以通过map来讲对象转换成其他类型,map返回的Stream类型是根据你map传递进去的函数的返回值决定的。代码如下:stringCollection.stream().map(String:toUpperCase).sorted(a,b)->b.compareTo(a)).forEach(System.out:printin);//"DDD2","DDD1","CCC","BBB3","BBB2","AAA2","AAA1"Map映射中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象,下面的示例展示了将字符串转换为大写字符串。你也可以通过map来讲对象转换成其他类型,map返回的Stream类型是根据你map传递进去的函数的返回值决定的。代码如下:stringCollection.stream().map(String:toUpperCase).sorted((a,b)->b.compareTo(a)).forEach(System.out:printin);//"DDD2","DDD1","CCC","BBB3","BBB2","AAA2","AAA1"Match 匹配Stream提供了多种匹配操作,允许检测指定的Predicate是否匹配整个Stream。所有的匹配操作都是最终操作,并返回一个boolean类型的值。代码如下:boolean anyStartsWithA=stringCollection.stream().anyMatch(s)->s.startsWith("a");System.out.printin(anystartsWithA);/∥true boolean allStartsWithA=stringCollection.stream().allMatch(s)->s.startsWith("a"));System.out.printin(allStartsWithA);//false boolean noneStartsWithZ=stringCollection.stream().noneMatch(s)->s.startsWith("z");System.out.printin(noneStartsWithZ);//trueCount计数计数是一个最终操作,返回Stream中元素的个数,返回值类型是long。代码如下:long startsWithB=stringCollection.stream().filter((s)->s.startsWith("b")).count();System.out.printin(startsWithB);//3Reduce规约这是一个最终操作,允许通过指定的函数来讲stream中的多个元素规约为一个元素,规越后的结果是通过Optional接口表示的:代码如下:Optional reduced=stringCollection.stream().sorted).reduce((51,52)->51+"#"+52);reduced.ifPresent(System.out::println);//"aaal#aaa2#bbb1#bbb2#bbb3#cCC#ddd1#ddd2"并行Streams前面提到过Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。下面的例子展示了是如何通过并行Stream来提升性能:首先我们创建一个没有重复元素的大表:代码如下:int max=1000000; List values=new Arraylist<>(max); for(inti=0;i< max;i++){ UUID uuid=UUID. randomUUID(); values. add(uuid. toString());}然后我们计算一下排序这个Stream要耗时多久,串行排序:代码如下:long to=System. nanoTime(); long count=values. stream(). sorted(). count(); System. out. println(count); long t1=System. nanoTime(); long millis =TimeUnit. NANOSECONDS. toMillis(t1-to); System. out. println(String. format("sequential sort took:%d ms", millis);∥串行耗时:899ms并行排序:代码如下:long to=System.nanoTime();long count=values.parallelStream().sorted).count();System.out.println(count);long t1=System.nanoTime();long mills=TimeUnit.NANOSECONDS.toMillis(t1-to);System.out.printin(String.format("parallel sort took:%d ms",millis));//并行排序耗时:472ms上面两个代码几乎是一样的,但是并行版的快了50%之多,唯一需要做的改动就是将stream()改为parallelStream()。Map前面提到过,Map类型不支持stream,不过Map提供了一些新的有用的方法来处理一些日常任务。代码如下:Map<Integer,String>map=new HashMap<>);for(inti=0;i<10;i++){map.putlfAbsent(i,"val"+i);}map.forEach(id,val)>System.out.println(val);以上代码很容易理解,putlfAbsent不需要我们做额外的存在性检查,而forEach则接收一个Consumer接口来对map里的每一个键值对进行操作。下面的例子展示了map上的其他有用的函数:代码如下:map. computelfPresent(3,(num, val)->val+num); map. get(3);//val33map. computelfPresent(9,(num, val)->nul); map. containsKey(9);//falsemap. computelfAbsent(23, num->"val"+num); map. containsKey(23);//true map. computelfAbsent(3, num->"bam"); map. get(3);//val33接下来展示如何在Map里删除一个键值全都匹配的项:代码如下:map.remove(3,"val3");map.get(3);//val33map.remove(3,"val33");map.get(3);/∥null另外一个有用的方法:代码如下:map.getOrDefault(42,"not found");//not found对Map的元素做合并也变得很容易了:代码如下:map.getOrDefault(42,"not found");//not found对Map的元素做合并也变得很容易了:代码如下:map.merge(9,"val9",(value,newValue)->value.concat(newValue));map.get(9);//val9map.merge(9,"concat",(value,newValue)->value.concat(newValue);map.get(9);//val9concat Merge做的事情是如果键名不存在则插入,否则则对原键对应的值做合并操作并重新插入到map中。九、Date API Java 8在包java.time下包含了一组全新的时间日期APl。新的日期APl和开源Joda-Time库差不多,但又不完全一样,下面的例子展示了这组新APl里最重要的一些部分:Clock时钟Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代System.currentTimeMils0来获取当前的微秒数。某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象。代码如下:Clock clock=Clock.systemDefaultZone();long millis =clock.mils();Instant instant=clock.instant();Date legacyDate=Date.from(instant);//legacy java.util.DateTimezones时区在新API中时区使用Zoneld来表示。时区可以很方便的使用静态方法of来获取到。时区定义了到UTS时间的时间差,在Instant时间点对象到本地日期对象之间转换的时候是极其重要的。代码如下:System.out.println(Zoneld.getAvailableZonelds());//prints all available timezone ids Zoneld zone1=Zoneld.of("Europe/Berlin");Zoneld zone2=Zoneld.of("Brazil/East");System.out.println(zone1.getRules();System.out.printin(zone2.getRules());LocalTime本地时间LocalTime 定义了一个没有时区信息的时间,例如晚上10点,或者17:30:15。下面的例子使用前面代码创建的时区创建了两个本地时间。之后比较时间并以小时和分钟为单位计算两个时间的时间差:代码如下:LocalTime now1=LocalTime.now(zone1);LocalTime now2=LocalTime.now(zone2);System.out.println(now1.isBefore(now2);//false long hoursBetween=ChronoUnit.HOURS.between(now1,now2);long minutesBetween=ChronoUnit.MINUTES.between(now1,now2);System.out.println(hoursBetween);//-3 System.out.printin(minutesBetween);//-239LocalTime 提供了多种工厂方法来简化对象的创建,包括解析时间字符串。代码如下:LocalTime late =LocalTime.of(23,59,59);System.out.println(late);//23:59:59DateTimeFormatter germanFormatter=Date TimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withLocale(Locale.GERMAN);LocalTime leetTime=LocalTime.parse("13:37",germanFormatter);System.out.printin(leetTime);//13:37LocalDate本地日期LocalDate表示了一个确切的日期,比如2014-03-11。该对象值是不可变的,用起来和LocalTime基本一致。下面的例子展示了如何给Date对象加减天/月/年。另外要注意的是这些对象是不可变的,操作返回的总是一个新实例。代码如下:LocalDate today=LocalDate.now();LocalDate tomorrow =today.plus(1,Chronounit.DAYS);LocalDate yesterday=tomorrow.minusDays(2);LocalDate independenceDay =LocalDate.of(2014,Month.JULY,4);DayofWeek dayofweek=independenceDay.getDayOfWeek();System.out.printin(dayofWeek);//FRIDAY 从字符串解析一个LocalDate类型和解析LocalTime一样简单:代码如下:DateTimeFormatter germanFormatter=Date TimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.GERMAN);LocalDate xmas =LocalDate.parse("24.12.2014",germanFormatter);System.out.println(xmas);//2014-12-24LocalDateTime 本地日期时间LocalDateTime同时表示了时间和日期,相当于前两节内容合并到一个对象上了。LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。LocalDateTime提供了一些能访问具体字段的方法。代码如下:LocalDate Time sylvester=LocalDate Time.of(2014,Month.DECEMBER,31,23,59,59);DayofWeek dayofWeek=sylvester.getDayofWeek();System.out.println(dayOfWeek);//WEDNESDAY Month month=sylvester.getMonth();System.out.println(month);//DECEMBER long minuteOfDay=sylvester getLong(ChronoField.MINUTE_OF_DAY);System.out.println(minuteOfDay);//1439只要附加上时区信息,就可以将其转换为一个时间点Instant对象,Instant时间点对象可以很容易的转换为老式的java.util.Date。代码如下:Instant instant=sylvester.atZone(Zoneld.systemDefault().tolnstant();Date legacyDate=Date.from(instant);System.out.printin(legacyDate);//Wed Dec 31 23:59:59 CET 2014格式化LocalDateTime和格式化时间和日期一样的,除了使用预定义好的格式外,我们也可以自己定义格式:代码如下:DateTimeFormatter formatter=DateTimeFormatter.ofPattern("MMM dd,yyyy-HH:mm");LocalDateTime parsed=LocalDateTime.parse("Nov 03,2014-07:13",formatter);String string=formatter.format(parsed);System.out.println(string);//Nov 03,2014-07:13和java.text.NumberFormat不一样的是新版的DateTimeFormatter是不可变的,所以它是线程安全的。十、Annotation 注解在Java8中支持多重注解了,先看个例子来理解一下是什么意思。首先定义一个包装类Hints注解用来放置一组具体的Hint注解:代码如下:@interface Hints{Hint]value();}@Repeatable(Hints.class)@interface Hint{String value();}Java8允许我们把同一个类型的注解使用多次,只需要给该注解标注一下@Repeatable即可。例1:使用包装类当容器来存多个注解(老方法)代码如下:@Hints({@Hint("hint1"),@Hint("hint2")})class Person}例2:使用多重注解(新方法)代码如下:@Hint("hint1")@Hint("hint2")class Person}第二个例子里java编译器会隐性的帮你定义好@Hints注解,了解这一点有助于你用反射来获取这些信息:代码如下:Hint hint=Person. class. getAnnotation(Hint. class); System. out. println(hint);//null Hints hints1=Person. class. getAnnotation(Hints. class); System. out. printin(hints1. value(). length);//2Hint[]hints2=Person.class.getAnnotationsBy Type(Hint.class);System.out.printin(hints2.length);//2即便我们没有在Person类上定义@Hints注解,我们还是可以通过 getAnnotation(Hints.class)来获取@Hints注解,更加方便的方法是使用getAnnotationsBy Type 可以直接获取到所有的@Hint注解。另外ava8的注解还增加到两种新的target上了:代码如下:@Target{ElementType.TYPE_PARAMETER,ElementType.TYPE_USE})@interface MyAnnotation}关于Java8的新特性就写到这了,肯定还有更多的特性等待发掘。JDK1.8里还有很多很有用的东西,比如Arrays.parallelSort,StampedLock和CompletableFuture等等。
2022年03月07日
504 阅读
0 评论
7 点赞
2022-02-28
JAVA map遍历
Map集合的2种循环方式。一种是通过map.entrySet()。另一种是map.keySet()。所有的集合都可以通过迭代器Iterator,进行遍历。package learn.javase; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** * 重要 * 遍历map的两种方式map.entrySet() map.keySet() * @author Jole * */ public class MapDemo { public static void main(String[] args) { Map<Integer ,String > map = new HashMap(); map.put(1, "111"); map.put(2, "2222"); //方式一 entrySet() Set<Map.Entry <Integer, String>> sets = map.entrySet(); //获取值1,通过for for(Map.Entry <Integer, String> entry : sets) { System.out.println("ssss:"+entry); System.out.println("key:"+entry.getKey()+"value:"+entry.getValue()); } //获取值2,通过iterator Iterator <Map.Entry <Integer, String>> itt = sets.iterator(); while(itt.hasNext()) { Map.Entry <Integer, String> entrys = itt.next(); System.out.println(entrys.getKey()+"----"+entrys.getValue()); } System.out.println(map.put(3, "222")); //方式二 keySet() Set<Integer> set = map.keySet(); Iterator it = set.iterator(); while(it.hasNext()) { System.out.println("Iterator="+it.next()); System.out.println("key:"+map.get(it.next())); } for(Integer in : set) { System.out.println(in); } } }
2022年02月28日
302 阅读
0 评论
2 点赞
2022-02-28
Scanner和Random类
Java的两个引用输入类型Scanner、Random类,Scanner用于接收键盘输入,Random用户产生随机数。引用类型也就是Sun公司为我们写好的类,我们直接使用就可以了。1、引用数据类型的使用导入包:知道用的这个类,在jdk的那个目录那个文件下。创建对象:格式, 类 对象 = new 类型();如何使用: 对象.类的方法()引用数据类型的使用与定义基本数据类型变量不同,引用数据类型的变量定义及赋值有一个相对固定的步骤或格式,如下:数据类型 变量名 = new 数据类型();每种引用数据类型都有其方法,我们可以调用该类型实例的方法。变量名.方法名();2、Scanner类Scanner类是引用数据类型的一种,我们可以使用该类来完成用户键盘录入,获取到录入的数据。导包import java.util.Scanner;创建对象实例Scanner sc = new Scanner(System.in);调用方法//用来接收控制台录入的数字 int i = sc.nextInt(); //用来接收控制台录入的字符串 String s = sc.next(); Scanner使用Demo:package java_learn_code; //导入包,指明类所在的的文件见,关键字import import java.util.Scanner; /** * 引用数据类型,使用步骤:1、导入包 。2、创建对象 3、通过对象调用方法 * @author Jole * Scanner的使用,所在目录java文件见-util文件夹 */ public class ScannerDemo { public static void main(String[] args) { System.out.print("请输入整数内容:"); //类型 变量名 = new 类型(); //创建出scanner,类变量 Scanner scan = new Scanner(System.in); //变量.功能方法,接受键盘输入 //功能:nextint()接受键盘输入的是整数 String str = scan.next(); System.out.println("\n您输入的内容是:"+str+1); } }3、Random类Random类也是属于引用类型,用于产生随机数的。Random类可以产生多种数据类型的随机数,在这里我们主要介绍生成整数与小数的方式。//用于产生[0,maxValue)范围的随机整数,包含0,不包含maxValue; public int nextInt(int maxValue) //用于产生[0,1)范围的随机小数,包含0.0,不包含1.0。 public double nextDouble()Random使用方式:import导包:所属包java.util.Random创建实例格式:Random 变量名 = new Random();Random类使用,产生随机整数、浮点数: package java_learn_code; //导入类所在的包,知道sun为我们写好的类所在位置 import java.util.Random; import java.util.stream.DoubleStream; /** * 随机数类Random引用类型的使用,产生随机整数\浮点数 * 使用步骤:1、导入包 2、创建对象 3、通过对象.方法() 进行使用 * 随机数,都是伪随机数,因为都是人编写的算法,而产生的随机数 */ public class RandomDemo { public static void main(String[] args) { //创建Random对象 Random ran = new Random(); //产生随机整数 //调用对象的方法nexInt(),产生整数,加参数表示产生0-参数内的整数 //注释不包含参数本身,例如nextInt(100),表示产生0-99中的整数。 int i = ran.nextInt(100); System.out.println(i); //产生随机浮点数 Random random = new Random(); double d =random.nextDouble(); System.out.println(d); } }注意:随机数,都是伪随机数,因为都是人编写的算法,而产生的随机数。
2022年02月28日
218 阅读
0 评论
0 点赞
2022-02-28
JAVA Socket TCP多线程文件上传
通过Java Socket编程,实现多线程文件上传。主要涉及ServerScoket服务端、Socket客户端、IO流操作、多线线程。客户端:package learn.javase.Update; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /** * 利用TCP的Socket\ServerSocket客户端向服务器上传文件 * 客户端 * @author Jole * */ public class UpClent { public static void main(String[] args) throws IOException{ Socket socket = new Socket("127.0.0.1",8888); OutputStream out = socket.getOutputStream(); //读取本地文件,并通过out输出流,发送给服务端 File file = new File("J:"+File.separator+"wxhandbook-master.zip"); FileInputStream in = new FileInputStream(file); byte[] data = new byte[1024]; int len =0; while((len=in.read(data))!=-1) { out.write(data, 0, len); } socket.shutdownOutput(); //获取服务器返回信息 InputStream info = socket.getInputStream(); int infoSize=info.read(data); System.out.println(new String(data, 0, infoSize)); info.close(); socket.close(); } } 多线程实现类:package learn.javase.Update; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Random; /** * 改造为多线程,服务端 * @author Jole * */ public class UpServerThread implements Runnable{ private Socket socket; public UpServerThread(Socket socket) { this.socket = socket; } @Override public void run() { try { //获取客户端输入流 InputStream in = socket.getInputStream(); //判断文件夹是否存在,不存在则新建 File file = new File("H:\\up"); if(!file.exists()) { file.mkdir(); } //设置文件名规则 String fileName = System.currentTimeMillis()+"_"+new Random().nextInt(9999)+".zip"; FileOutputStream out = new FileOutputStream(file+File.separator+fileName); //读取客户端发送数据,并写入到H:\\up文件夹下面 byte[] data = new byte[1024]; int len = 0; while((len=in.read(data))!=-1) { out.write(data, 0, len); } //返回消息给客户端,上传成功信息 OutputStream outInfo = socket.getOutputStream(); outInfo.write("上传成功".getBytes()); outInfo.close(); out.close(); socket.close(); }catch(Exception e) { e.printStackTrace(); } } } 服务端线程启动类:package learn.javase.Update; import java.net.ServerSocket; import java.net.Socket; /** * 启动服务器多线程 * @author Jole * */ public class UpServerMainThread { public static void main(String[] args) throws Exception{ ServerSocket server = new ServerSocket(8888); while(true) { Socket socket = server.accept(); new Thread(new UpServerThread(socket)).start(); } } }
2022年02月28日
299 阅读
0 评论
1 点赞
2022-02-28
JAVA Socket UDP实现聊天
通过Socket网络编程,UDP实现简单聊天。主要涉及DatagramSocket进行数据传输、DatagramPacket进行数据包封装,2个类。发送端:package learn.javase.chat; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.Scanner; /** * 控制台输入;实现聊天。 * 发送方 * @author Jole * */ public class UdpSend { public static void main(String[] args) throws Exception{ Scanner scan = new Scanner(System.in); InetAddress ia = InetAddress.getByName("192.168.1.4"); DatagramSocket socket = new DatagramSocket(); while(true) { String chatInfo = scan.nextLine(); byte[] info = chatInfo.getBytes(); DatagramPacket pack = new DatagramPacket(info, info.length, ia, 6000); socket.send(pack); } } } 接收端:package learn.javase.chat; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /** * UDP:接收方 * @author Jole * */ public class UdpReceive { public static void main(String[] args) throws Exception{ DatagramSocket socket = new DatagramSocket(6000); byte[] info = new byte[1024]; while(true) { DatagramPacket pack = new DatagramPacket(info, info.length); socket.receive(pack); InetAddress ia = pack.getAddress(); System.out.println(ia.getHostName()+"-"+pack.getPort()+":"+new String(info,0,pack.getLength())); } } }
2022年02月28日
223 阅读
0 评论
1 点赞
2022-02-28
DBUtils进行数据库CRUD
通过读取properties获取链接数据库信息,利用apache开源数据库操作工具包DBUtils进行数据库CRUD操作。properties文件:driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test user=root password=11111通过dbutils自定义获取数据库连接对象:package learn.javase.jdbc; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; public class JdbcUtils{ private static Connection conn; private static String driverClass; private static String url; private static String user; private static String password; static { try { getReadConfig(); Class.forName(driverClass); conn = DriverManager.getConnection(url, user, password); }catch(Exception e) { new RuntimeException("链接数据库失败!"); } } private static void getReadConfig() throws Exception{ InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties pro = new Properties(); pro.load(in); driverClass =pro.getProperty("driverClass"); url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); } public static Connection getConnection() { return conn; } } 使用工具包中的QueryRunner进行数据库的CRUD操作:package learn.javase.jdbc; import java.sql.Connection; import java.sql.SQLException; import org.apache.commons.dbutils.DbUtils; import org.apache.commons.dbutils.QueryRunner; /** * 利用apatche的DBUtils工具包,添加\修改\删除数据 * @author Jole * */ public class DbUtilsDemo { private static Connection conn = JdbcUtils.getConnection(); private static QueryRunner qr = new QueryRunner(); public static void main(String[] args) throws Exception{ // insert(); // update(); delte(); } public static void insert() throws SQLException{ String sql = "insert into my_user(u_id,u_name,u_age) values(11111,'inster',10)"; Object[] param = {}; int n = qr.update(conn, sql, param); System.out.println(n); DbUtils.close(conn); } public static void update() throws SQLException{ String sql ="update my_user set u_name=? ,u_age=? where u_id=?"; Object[] param = {"ceshi",1000,11111}; int n = qr.update(conn, sql, param); DbUtils.close(conn); System.out.println(n); } public static void delte() throws SQLException{ String sql = "delete from my_user where u_id=?"; int n = qr.update(conn, sql, 11111); DbUtils.close(conn); System.out.println(n); } } 封装QueryRunner返回结果成对象:要封装成的对象Userpackage learn.javase.jdbc; public class User { private String u_id; private String u_name; private String u_age; public String getU_id() { return u_id; } public void setU_id(String u_id) { this.u_id = u_id; } public String getU_name() { return u_name; } public void setU_name(String u_name) { this.u_name = u_name; } public String getU_age() { return u_age; } public void setU_age(String u_age) { this.u_age = u_age; } public User() { super(); // TODO Auto-generated constructor stub } public User(String u_id, String u_name, String u_age) { super(); this.u_id = u_id; this.u_name = u_name; this.u_age = u_age; } @Override public String toString() { return "User [u_id=" + u_id + ", u_name=" + u_name + ", u_age=" + u_age + "]"; } } 根据返回结果,通过实现ResultHandler接口的实现类,封装对象:package learn.javase.jdbc; import java.sql.Connection; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.ArrayHandler; import org.apache.commons.dbutils.handlers.ArrayListHandler; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ColumnListHandler; import org.apache.commons.dbutils.handlers.MapHandler; import org.apache.commons.dbutils.handlers.MapListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; /** * 利用开源apache的commons-dbutils-1.7.jar的QueryRunner封装数据 * @author Jole * */ public class QueryRunnerDemo01 { public static final Connection conn = JdbcUtils.getConnection(); public static final QueryRunner qr = new QueryRunner(); public static void main(String[] args) throws Exception { // TODO Auto-generated method stub // getInfo(); // getInfo2(); // getInfo3(); // getInfo4(); // getInfo5(); // getInfo6(); // getInfo7(); getInfo8(); } //ArrayHandler 第一行 public static void getInfo() throws Exception{ String sql ="select * from my_user"; Object[] rs = qr.query(conn, sql, new ArrayHandler()); for(Object obj : rs) { System.out.print(obj + "\t"); } } //ArrayListHandler 所有记录 public static void getInfo2() throws Exception{ String sql ="select * from my_user"; List<Object[]> rs = qr.query(conn, sql, new ArrayListHandler()); for(Object[] objs : rs) { for(Object obj : objs) { System.out.print(obj + "\t"); } System.out.println(); } } //javaBean 第一行封装成对象 public static void getInfo3() throws Exception{ String sql ="select * from my_user"; User user = qr.query(conn, sql, new BeanHandler<User>(User.class)); System.out.println(user); } //javaBean 所有记录封装成对象 public static void getInfo4() throws Exception{ String sql ="select * from my_user"; List<User> userList = qr.query(conn, sql, new BeanListHandler<User>(User.class)); for(User user : userList) { System.out.println(user); } } //ColumnListHandler所有记录的某列值 public static void getInfo5() throws Exception{ String sql ="select * from my_user"; List<Object> list = (List<Object>) qr.query(conn, sql, new ColumnListHandler("u_name")); for(Object obj : list) { System.out.println(obj); } } //ScalarHandler返回单个值 public static void getInfo6() throws Exception{ String sql ="select count(*) from my_user"; Long count = qr.query(conn, sql, new ScalarHandler<Long>()); System.out.println(count); } //MapHandler将第一行数据封到map中 public static void getInfo7() throws Exception{ String sql ="select * from my_user"; Map<String, Object> map = qr.query(conn, sql, new MapHandler()); Set<String> set =map.keySet(); for(String key : set) { System.out.println(key+" "+map.get(key)); } } //MapListHandler将所有数据封到list中的map中 public static void getInfo8() throws Exception{ String sql ="select * from my_user"; List<Map<String, Object>> list= qr.query(conn, sql, new MapListHandler()); for(Map<String, Object> map : list) { for(String key : map.keySet()) { System.out.print(key+" "+ map.get(key)); } System.out.println(); } } } 主要涉及的jar包:commons-dbutils-1.7.jar(基本的CRUD)、mysql-connector-java-5.1.37-bin.jar(数据库连接驱动)
2022年02月28日
361 阅读
0 评论
1 点赞
1
...
3
4
5