Java on sin-coder https://sin-coder.github.io/tags/java/ Recent content in Java on sin-coder Hugo -- gohugo.io en-us Sun, 22 Dec 2019 21:14:28 +0800 Java面向对象之接口 https://sin-coder.github.io/program/javaintf/ Sun, 22 Dec 2019 21:14:28 +0800 https://sin-coder.github.io/program/javaintf/ Java面向对象和接口 在Java编程语言中接口是一个抽象类型,是抽象方法的结合,一个类通过继承接口的方法来继承接口的 抽象方法;除非实现接口的类是抽象类,否则该类要实现接口中的所有方法;接口无法被实例化,但是可以 被实现;在Java中,接口类型可以用来声明一个变量 一、接口和类的异同 1.接口和类的相似点 一个接口可以有多个方法 接口文件保存在.java文件中,文件名使用接口名 接口的字节码文件保存在.class文件中 接口相应的字节码文件必须在与包名称匹配的目录中 2.接口和类的主要区别 接口不能用于实例化对象 接口没有构造方法 接口的所有方法必须是抽象方法 接口不能包含成员变量,除了static和final变量 接口可以被类继承或者实现 3.接口特性 接口中的方法会被隐式地指定为public abstract 接口可以含有变量,但是会被隐式地指定为public static final 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现 二、接口的操作 1.接口的声明 [可见度] interface 接口名称 [extends 其他的接口名]{ //声明变量 //声明方法 } 2.接口的实现 类使用implements关键字来实现接口,类声明中,implements关键字放在class声明后 ...implements 接口名称[,其他接口名称,.....] 类实现接口的时候必须实现接口的所有方法,否则就要被定义为抽象类 重写接口中声明的方法时,有以下要求 类实现接口中的方法时,不能抛出强制性的异常,只能在接口中,或者继承接口的抽象类中抛出 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型 Java中的包(Package) https://sin-coder.github.io/program/package/ Sat, 21 Dec 2019 21:14:28 +0800 https://sin-coder.github.io/program/package/ Java中的包(Package) 一、Java中包的作用 在Java中为了更好的组织类,提供了包机制,可以看成是区别类名的命名空间,主要作用如下: 把功能相似或者相关的类或接口组织在同一个包中,方便类的查找和使用 包采用了类似文件夹一样的树形目录的存储方式,同一个包中类的名字是不同的,不同包中类的名字可以是 相同的,当同时调用不同包中相同类名的类时,应该加上包名加以区分,避免冲突 包限定了访问权限,拥有包访问权限的类才能访问某个包中的类 二、包的使用 1.包语句的格式 包语句的语法格式为 package pkg1[.pkg2[.pkg3]] //示例如下 package net.java.util; //注意包声明语句后有分号 public class Test{} //那么这个文件的保存路径应该是这样的:net/java/util/Test.java 一个包可以定义为一组相互联系的类型,为这些类型提供访问保护和命名空间管理的功能;在实际的应用 中,可以将自己完成的一组类或者接口等打包,方便管理和使用 2.创建包 包声明应该在源文件的第一行,每个源文件只能有一个包的声明,这个文件中的每个类型都应用于它;如 果一个源文件没有包的声明,那么其中的类都将被放到一个无名的包中,创建包的包名应该最好使用小写的 3.使用包 为了能够使用某一个包的成员,需要在Java程序中明确导入该包,使用import语句即可完成; 在Java源文件中的import语句应位于package语句之后,所有类的定义之前;格式如下: import package1[.package2...](classname|*); 如果在一个包中一个类想要使用本包中的任何一个类,包名是可以忽略的 值得注意的是import是导入包所包含的类,而不能导入包,通常情况下,我们也不是只导入包中的某个类 而是导入包下所有的类;Java编译器默认为所有的Java程序导入了JDK中java.lang包中的所有类,其中定义了 一些常用的类,如Objetc、Math等,因此我们可以直接使用这些类而不必显示导入,当使用其他类时必须导入 并且import实际上导入的是每一个类的.class文件,并不是.java类型的文件 4.Java中类的搜索路径 在安装JDK时,我们已经设置了环境变量CLASSPATH,在Windos下的cmd中可以通过set命令查看 #一个CLASSPATH可能包含好几个路径,多路径应该使用分割符进行分开 C:\Users\Administrator>set CLASSPATH CLASSPATH=.;C:\Program Files\Java\jdk1.8.0_91\lib; C:\Program Files\Java\jdk1. Java面向对象之抽象类 https://sin-coder.github.io/program/abstract/ Sat, 21 Dec 2019 21:14:28 +0800 https://sin-coder.github.io/program/abstract/ Java面向对象之抽象类 面向对象的设计原因中所有的对象都是通过类来进行描绘的,但是并不是所有的类都是用来描述对象的, 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的就是抽象类 抽象类正常类最大的区别就是不能实例化对象,所以抽象类必须被继承,才能被使用;但是抽象类的其 它功能如:成员变量、成员方法和构造方法依然存在 一、抽象类的定义和使用 在Java语言中使用abstract class来定义抽象类,而且只能通过其他类来继承抽象类 //文件名为Test.java public abstract class Test{} //文件名为smallTest public class smallTest extends Test{} 二、抽象方法 抽象方法必须是一个特别的成员方法,该方法的具体实现是由它的子类确定的,那么可以在父类中声明 该方法是一个抽象方法;而且抽象方法所在的类一定是抽象类; abstract关键词同样可以用来声明抽象方法,抽象方法只包含一个方法名而没有方法体;抽象方法没有定 义,方法名后面直接跟上一个分号,而不是花括号 public abstract class Employee{ public abstract int getMsg();//抽象方法 } 任何子类必须重写父类的抽象方法,或者声明自身是一个抽象类; 三、其他规定 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类 抽象类中的抽象方法只是声明,不包含方法体,即不给出方法的具体实现 构造方法和类方法(用static方法修饰的方法)不能声明为抽象的方法 Java面向对象总结 https://sin-coder.github.io/program/javaoop/ Fri, 20 Dec 2019 00:14:28 +0800 https://sin-coder.github.io/program/javaoop/ Java面向对象总结 一、类和对象 Java中的类可以包含局部变量、成员变量、类变量 局部变量:在方法、构造方法中定义的变量 成员变量:定义在类中,方法体之外的变量。可以被类中的各种方法使用 类变量:定义在各种类中,方法体之外。必须声明为static类型 构造方法 : 如果没有显式地为类定义构造方法,Java编译器会为该类提供一个默认的构造方法。在创 建一个对象的时候,至少要调用一个构造方法 Java中import语句执行的过程,import语句主要是提供一个合理的路径,使得编译器能够找到某个类 Java中的类有若干访问级别:抽象类、final类、内部类、匿名类 Java中强制要求类名和文件名相同,是因为在引用其他类的时候无需显式的声明,在编译时会根据类 名去寻找同名文件 Java中包的作用就是防止名字相同的类产生冲突。编译器在编译时直接根据package指定的信息直接 将生成的class文件生成到对应文件的目录中,比如package com.util.Test,编译器就将生成的.java文件 放于./com/util/Test/这个目录下 import的作用是为了简化使用package之后的实例化的代码,就是将new java.net.Socket()简化成 new Socket() 一个Java文件中只能包含一个Public的类 this是指向对象本身的指针,super是指向父类对象的一个指针 new关键字的一个作用,为对象分配内存空间、引起对象构造方法的调用,为对象返回一个引用 对象和引用的区别,对象是具体的一个实例,使用new创建一个对象时,是在堆内存中开辟一块空间 引用名称存放的对象的地址 二、Java中的继承 在Java中可以通过extends关键字可以声明一个类是从另外一个类继承而来的 Java中不支持多继承,但是支持多重继承 子类可以拥有父类非private的属性和方法,子类可以用自己的方式实现父类的方法 Java中所有的类都是继承于java.lang.Object这个祖先类,如果一个类没有显示继承,则默认情况 下继承Object 祖先类 implements关键字可以变相的使Java具有多继承的特性,同时实现多个接口 final关键字声明类可以把类定义为不能继承的,即是最终类。或者用于修饰方法,该方法不能被子类重写 final修饰类中的属性或者变量时,无论是基本类型还是引用类型 Java文件被编译成class文件时,在子类的所有构造函数中的第一行会默认添加super()语句,在执行子类 的构造函数前,总是会先执行父类的构造函数,执行父类构造函数的语句只能放在函数内语句的首句,不然 报错;如果父类不含默认的构造函数,子类中的super()语句就会执行失败 Object类是所有类的根父类,可以用于参数的传递,当你不清楚函数需要的参数是什么类型的,可以使 用Object类来代替,Object可以代替任何类 三、重写和重载 1.重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和参数都不能变 Java中的ArrayDeque和LinkedList的使用 https://sin-coder.github.io/datastructure/deque_linked/ Tue, 10 Dec 2019 16:10:36 +0800 https://sin-coder.github.io/datastructure/deque_linked/ Java中的ArrayDeque和LinkedList的使用 在Java的集合框架中,ArrayDeque和LinkdedList是实现栈和队列的两种不同方式,那么应该如何使用, 才能使自己构造的数据结构解决问题时性能更好呢,先上一张继承关系表 从上图中我们可以看到,ArrayDeque是继承于Deque接口,LinkedList继承于List接口和Deque接口,看 起来功能要更加强大,那么我们从几个方面来进行比较 从这张表格可以看出ArrayDeque和LinkedList的主要区别就是数组和链表的区别,二者都能用作双向队列、 栈;但是使用ArrayDeque当数据不断插入时,底层数组可能扩容,对性能的影响是比较大的;LinkedList底层 是使用的双向链表,不存在扩容的问题,但由于链表,占用的存储空间更大。二者各有优劣,所以综合来看: 当做队列或栈使用并且数据量比较少时,使用ArrayDeque,占用的存储空间更小 当做队列或栈使用并且数据量很大时,使用LinkjedList,这样不用扩容对性能的影响 当需要随机访问时,使用ArrayDeque,数组有先天的优势 Java和Python中如何使用大顶堆 https://sin-coder.github.io/program/javapqueue/ Tue, 03 Dec 2019 21:14:28 +0800 https://sin-coder.github.io/program/javapqueue/ Java和Python中如何使用大顶堆 在数据结构之容器的那篇文章中,我们对于优先队列即堆这种数据结构的底层实现进行了剖析,在实际的 应用中我们不必自己去实现一个堆,主流的编程语言都提供了相关的集合模块,比如Java中的PriorityQueue 类,Python中的heapq模块。但是这两种语言中实现的堆都是小顶堆(根节点的元素小于左右节点元素的值), 当需要使用大顶堆时该如何解决呢?比如典型的最大的K个元素需要用小顶堆解决,但是最小的K个元素不就 是需要使用一个大顶堆来解决了吗! 具体的解决方案如下: 一、通用的方法: 取反 通用的解决方法就是跟语言没有关系的解法,想要构造一个大顶堆,只要保证根节点大于左右节点即可, 所以我们可以将数据取成相反数再添加到小顶堆中去,取出时再对数据进行取反即可实现大顶堆的效果 二、针对Java的方法 优先队列中存放的是基本数据类型的包装类(Integer、Long)或者自定义的包装类。对于基本数据类型 的包装器类,优先队列中元素默认排列顺序是升序排列的,也就是说是小顶堆,但是既然是默认的就可以进 行更改。此外,对于自定义的类来说,需要自己定义比较器,比如: //自定义比较器,降序排列 public static Comparator<Integer> cmp = new Comparator<Integer>(){ public int compare(Integer e1,Integer e2){ return e2 - e1; } } //声明对象时 Queue<Integer> pqueue = new PriorityQueue<Integer>(); //不使用比较器,默认升序排列,即小顶堆 Queue<Integer> pqueue = new PriorityQueue<Integer>(cmp); //使用比较器,降序排列,即为大顶堆 //比较器升降序的声明 Comparator<Object> cmp = new Comparator<Object>(){ public int compare(Object o1,Object o2){ return o1 - o2 //升序 return o2 - o1 //降序 } } 所以在实际解决问题的过程中如果需要使用大顶堆可以这样声明 数据结构之容器 https://sin-coder.github.io/datastructure/container/ Thu, 28 Nov 2019 17:01:10 +0800 https://sin-coder.github.io/datastructure/container/ 一、概述 1.什么是数据结构中的容器? 容器是一种把多个元素组织在一起的数据结构,也可以理解为一种可以包含其他类型对象作为元素的 的对象。容器是仅仅用来存放数据的,本身没有取出元素这种能力,大多数情况下是通过可迭代对象来 操作容器 容器这种数据结构在各种编程语言中都有相应的实现,比如我们经常会比较熟悉的C++的标准模板库 (Standard Template Library,STL)、Java的集合框架(Java Collections Framework,JCF)、而在 Python中更是将容器类型的数据结构作为其基本数据类型、Go语言也有内建的容器和相应的标准库, 本篇博客便是在总结各种容器使用及原理的基础上,对Java、Python中相同的类型的容器做一个横向的 对比,以便于日后的总结和复习 2.Java集合框架简介 (1)泛型的机制 Java中的容器就是可以容纳其他Java对象的对象,且Java容器中只能存放对象,对于一些基本的数据 类型(比如int、long、float、double等),需要将其包装成对象类型之后(Interger、Long、Float、Double 等)才能放到容器里,很多时候拆包装和解包装使能够自动完成的 Java容器能够容纳任何类型的对象,表面上是通过泛型机制完成的。事实上,所有容器的内部存放的都 是Object类的对象,所有的对象都是Object类型的子类。泛型机制只是简化了编程,由编译器自动帮助我们 完成了强制类型的转换而已,示例代码如下 ArrayList<String> list = new ArrayList<String>(); //参数化类型 list.add(new String("csuyzz")); String name = list,get(0); //容器中存放的Object类的对象隐式转换成为String类型的对象 此外,Java里的对象都在堆上,且对象只能通过引用(reference)来访问,容器里存放的其实是对 象的引用而不是对象的本身 (2)接口和实现(Interfaces and Implementations) 在Java 的集合框架中共定义了14种容器的接口,关系图如下所示,Map接口没有继承自Collection的 接口,因为Map接口是关联式的容器而不是集合,但也可以从Map转换到Coolection;Stack已经被Deque 所取代 接口的实现如下表所示 ImplementationsHash TableResizable ArrayBalanced TreeLinked ListHash Table + Linked ListInterfacesSetHashSetTreeSetLinkedHashSetListArrayListLinkedListDequeArrayDequeLinkedListMapHashMapTreeMapLinkedHashMap > (3) 迭代器 常见数据结构的定义 https://sin-coder.github.io/datastructure/defindatastructure/ Fri, 15 Nov 2019 14:01:10 +0800 https://sin-coder.github.io/datastructure/defindatastructure/ 常见数据结构的定义 一、链表(以singly-linked list为例) 1.Java public class ListNode{ int val; ListNode next; //如果是双向链表,则会为left or right ListNode(int x) { val = x; next = null; } } 2.Python class ListNode: def __init__(self,x): self.val = x self.next = Node 3.C struct ListNode{ int val; struct ListNode *next; }; 4.Go type ListNode struct{ Val int Next *ListNode } 二、二叉树(Binary Tree Node) 1.Java //Definition for a binary tree node public class TreeNode{ int val; TreeNode left; TreeNode right; TreeNode(int x){val = x;} } 2.