来到小组已经有很长时间了,现在已经开始学习关于服务器的知识,但是java的基础不能忘记,所以对容易忘记的知识点做一下总结。 ps:java是自学的,可能有错哦~ @_@
java基础知识
1、基本数据类型对应的引用类型
byte——Byte long——Long short——Short float——Float boolean——Boolean double——Double char——Character int——Integer
2、关于构造方法
①在一个类的构造方法中可以通过this关键字调用本类的其他构造方法,但必须在第一行并且只能有一个。可以通过super关键字调用本类的父类其他构造方法,但必须在第一行并且只能有一个。
②如果父类仅声明了有参构方法,没有声明无参构造方法,则子类必须重写父类构造方法。但如果父类有无参构造方法则子类可以不重写父类构造方法。
③在执行子类的构造方法前,会自动调用父类没有参数的构造方法(无需写super()),如果不想调用父类中没有参数的构造方法而想要调用父类中有参数的构造方法,则必须在子类构造方法的第一行上写super(参数)。注意:如果父类只有有参构造方法而没有无参构造方法,但子类的构造方法中又没有用super(参数)则会发生错误。
3、类的继承和重写
①java支持多层继承,当B类继承A类,C类继承B类。则C类可调用A类和B类中的方法和成员变量。
②当父类的方法被子类重写时,直接调用方法,调用的是子类的方法,要想调用父类已被重写的方法则使用super关键字调用。父类中的静态方法可以被子类继承。但不能被子类重写。如果在子类中写一个和父类中一样的静态方法,那么该静态方法由该子类特有,两者不构成重写关系。
4、多态调用
A是类或接口,B是继承A类或实现了A接口的类。
A a=new B(); 这是向上转型,向上转型后如果子类和父类有相同名称的成员变量时,调用的是父类的成员变量。当子类重写父类方法时,调用的是子类方法。子类的特有方法不能调用。
B b=(B)a; 这是向下转型,必须先向上转型再向下转型,否则不能转。
5、this关键字和super关键字的用法
this:
①this表示本类。
②使用this关键字可以在本类构造方法中调用本类的其他构造方法。
③在一个类中,如果成员变量和局部变量同名时,可以使用this调用成员变量。
super:
①在子类的构造方法中,可以使用super调用父类的构造方法。
②在子类中可以通过super来调用父类中已被重写的方法和同名的成员变量。
6、抽象类和接口
①抽象类中可以有普通方法也可以有抽象方法。抽象方法必须被继承的非抽象类重写。
②abstract不能和private、static、final、native同时出现。
③定义接口的格式:
[public] interface 接口名称{
[public] [static] [final] 数据类型 成员变量名=值;
[public] [abstract] 返回值类型 方法名(参数列表);
}
[]中的都是默认的可以不写。
④接口可以通过extends继承多个接口,抽象类实现接口可以不重写方法,普通类继承抽象类或实现接口必须重写所有的抽象方法。
⑤一个类只能继承一个类但可以实现多个接口。
7、作用域修饰关键字
public | protected | default(默认) | private | |
同一类中 | √ | √ | √ | √ |
同一包中 | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包的无关类 | √ |
注:protected在不同包中,只能在子类中使用。
8、代码块
①局部代码块——定义在方法或语句中
用来限制变量的作用域,在里面定义的变量,在外面失效。
②构造代码块——定义在成员变量的位置
优先于构造方法执行,每创建一个实例对象均会执行一次构造代码块。
③静态代码块——定义在成员变量的位置并用static修饰
它优先于main方法执行,优先于构造代码块执行,当以任意形式第一次使用到该类的时候执行(使用子类也执行),只执行一次。
9、String类和StringBuffer类和StringBuilder类的区别
StringBuffer类和StringBuilder类是字符串缓冲区,比String的效率高而且节约空间。
StringBuilder效率高但线程不安全。
StringBuffer效率低但线程安全。 (推荐使用)
10、数字类型和字符串类型的互转
int i=1;
String s=“2”;
数字转字符串:
①s=i+""; 会产生两个String对象。
②s=String.valueOf(i); 只产生一个对象。
字符串转数字:
①i=Integer.parseInt(s); 不产生多余对象。
②i=Integer.valueOf(s); 相当于new Integer(Integer.parseInt(s)); 返回Integer类型多产生一个对象。
11、集合容器
List接口——存储有重复元素且元素是有序的。(有序指的是存储顺序)
常用的有:
①ArrayList(底层结构是数组结构,增删慢、查找快、线程不安全)
②LinkedList(底层结构是链表结构,增删快、查找慢、线程不安全)
Set接口——存储无重复元素且元素是无序的,根据哈希表存储数据,当哈希值相同(根据hashCode()判断)且equals为true时元素视为相同元素。
常用的有:
①HashSet(底层采用HashMap实现、线程不安全)
②LinkedHashSet(基于链表的哈希表实现,继承自HashSet,特征保持存取顺序、线程不安全)
Map接口——(无序,采用键值对方式,键不能重复,值可以重复)
常用的有:
①HashMap
②LinkedHashMap(继承HashMap,保持存取顺序)
注:增强for不能遍历Map,但是可以通过KeySet遍历,也可以使用Entry(Map的内部类)进行遍历,推荐使用Entry效率高。
③Properties (继承Hashtable,Map集合的方法都可以用)
它没有泛型,键值都是字符串,他是一个可以持久化的集合,通过IO流实现数据的持久化存储。
12、内部类
-
内部类可以使用private、protected、static、final、abstract等修饰符修饰。
-
内部类用final修饰,则表明内部类不能被继承。
-
内部类用abstract修饰,则需要被其他内部类继承。
-
内部类也可以是接口,该接口必须被另一个内部类来实现
-
内部类不能和外部类同名,内部类中还可以继续定义内部类。
-
内部类中可以直接使用外部类的变量和方法(包括私有)。
-
外部类中引用内部类时,必须先使用new创建一个对象,然后通过 对象.名称调用内部类中的数据。
-
在其他类中引用内部类的方法 外部类名.内部类名 变量名=new 外部类名().new 内部类名();
-
非静态内部类不能声明静态成员,只有静态内部类才可以声明静态成员。
①成员内部类——声明在成员变量的位置,不能用static修饰
public class Demo {
int i = 1;
class Inner {
int i = 2;
public void inner() {
int i = 3;
System.out.println(i);// 3
System.out.println(this.i);// 2
System.out.println(Demo.this.i);// 1
}
}
}
②局部内部类——定义在局部变量的位置
class Demo {
public void out() {
class Inner {
public void inner() {
System.out.println("局部内部类");
}
}
Inner in = new Inner();
in.inner();
}
}
思路:想要在其他类中调用局部内部类中的方法,在外部类的方法中创建局部内部类的实例对象并调用需要执行方法。
③匿名内部类——如果一个内部类只使用一次的话可以定义匿名内部类
new 接口或父类{
方法或重写的抽象方法
}[.父类的方法或成员变量];
④静态内部类——声明在成员变量的位置,用static修饰(只可以访问外部类的静态成员和静态方法)
调用方法:外部类名.内部类名 变量名=new 外部类名().new 内部类名();
13、异常处理
异常处理的格式:
try {
可能出现错误的代码
}catch(异常类名 变量名){
异常的处理方式
}final{
必须要执行的代码
}
try检测到异常发生,将异常对象抛给catch,catch捕获该异常(catch可有多个),catch执行完程序正常运行。final中的代码是无论发生什么情况都执行的代码(除了System.exit(0))。
多个catch注意事项:多个catch要注意顺序,异常类是平级则没有顺序,父子级关系的异常父类放下面。
子类重写父类方法的时候,异常处理:
①如果父类的方法抛出了异常,子类重写后可以抛出异常,也可以不抛出异常。但如果抛异常,异常必须是父类抛出的异常的子类(平级都不行)。
②如果父类的方法没有抛出了异常,子类重写后不可以抛出异常,只能用try{}catch{}处理。
自定义异常:
①自定义的异常必须继承Throwable或它的子类(一般继承RuntimeException或Exception)。
②在有参构造方法中,使用有super(参数)将异常信息传递给父类,再写一个空参构造方法。
14、IO流
盘符 "/"表示UNIX中的路径名分隔符,"\\"表示windows 路径名分隔符。(因为\是转义字符所以用两个)
windows (;)是目录分隔符,Linux (:)是目录分隔符
output指将程序写到硬盘中去,input指的是将文件加载到程序中去。
字节输入流:InputStream——FileInputStream
字节输出流:OutputStream——FileOutputStream
字符输入流:Reader——FileReade(专本用于读写文本文件)
字符输出流:Write——FileWriter
转换流:InputStreamReader、OutputStreamWriter
缓冲流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
对象流:ObjectOutputStream、ObjectInputStream
打印流:PrintStream、PrintWriter
15、多线程
jvm只有一个堆区(heap)被所有线程共享,每个线程都有一个栈区。(多个线程成员变量共享)
创建线程的3种方法:
1.继承Thread类
①声明一个类继承Thread类
②该子类重写run方法
③创建一个子类实例对象,就是创建了一个线程对象
④调用start方法,开启线程并让线程执行,同时还告诉jvm去调用run方法,run方法中放线程需要执行的代码。
2.实现Runnable接口
①声明一个类实现Runnable接口
②重写run方法
③创建Thread类实例对象,在构造方法中传递Runnable接口的实现类
④调用Thread类的start()方法
好处:避免了单继承的局限性,降低了程序的耦合性。
3.实现Callable接口,使用线程池(推荐)
①声明一个类实现Callable接口
②重写call方法
③调用Executors类的newFixedThreadPool(线程个数)方法返回ExecutorsService接口的实现类(创建了一个线程池)
④然后再用该实现类调用submit(Callable接口的实现类)方法执行线程,返回Future<T> 类
⑤通过Future<T>类的get()方法拿到call方法的返回值。
优点:call相当于run但是有返回值也可以抛异常。
要实现一个线程的异步计算,则在自己写的接口实现类里面写一个有参构造方法。
多线程执行一块数据可能引发并发异常,为了安全则使用锁(线程安全后速度就变慢了)。
有3种锁:①同步代码块,②同步方法③Lock接口(推荐)
注:多线程涉及到多锁,这些锁存在者交叉,就可能导致死锁现象。
线程状态图:
16、网络编程——UDP
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接,可能造成数据丢失,数据必须在64KB以内。由DatagramPacket类(用于封包数据)和DatagramSocket类(数据传输)来完成。(先运行接收端后运行发送端)
实现UDP协议的发送端:
①创建DatagramPacket对象封装数据和接收的地址和端口号。
②创建DatagramSocket。
③通过DatagramSocket的实例类,调用send方法发送数据包。
④关闭资源(关DatagramSocket)。
实现UDP协议的接收端:
①创建DatagramSocket对象绑定端口号(必须和发送端封装的端口号一样)。
②创建字节数组,用于接收发来的数据。
③创建DatagramPacket对象绑定用来接收发来数据的字节数组及长度。
④通过DatagramSocket的实例类,调用receive方法接收数据,并存放到数据包中。
⑤拆包:发送方的IP地址,接收的字节长度,发送方的端口号。
⑥关闭资源。
17、网络编程——TCP
TCP是面向连接的通信协议,即在数据传输前,数据的服务器端和客户端建立逻辑连接,需要进行三次握手,数据不会丢失,通过Socket类(客户端的套接字)和ServerSocket类(服务器的套接字)来完成(先运行服务器端后运行客户端)
实现TCP协议的服务器端:
①创建ServerSocket对象并绑定端口。
②调用服务器的套接字对象中的方法accept()。获取客户端的套接字对象。
③通过客户端的套接字对象,获取字节输入流读取客户端发送过来的数据。
④服务器向客户端回数据,通过客户端套接字对象获取字节输出流。
⑤先关闭客户端的套接字,再关闭服务器的套接字。
实现TCP协议的客户端:
①创建Socket对象并绑定服务器端的ip地址和端口号。
②通过客户端的套接字对象的方法获取字节输出流,将数据写想服务器。
③读取服务器发来的数据,使用套接字对象获取的字节输入流。
④关闭客户端的套接字对象。
18、反射技术
获取类的class文件对象的3种方法
①通过对象获得
A a = new A();
Class c = a.getClass();
②通过类名获得
Class c=A.class;
③通过Class类的静态方法获得
Class c=Class.forName("包名+类名");
java 9开始不推荐直接使用Class类的newInstance()方法直接获得此Class对象的实例化对象,而是使用Class类的getDeclaredConstructor().newInstance()方法间接获得此Class对象的实例化对象。
通过反射技术读取bin路径下存储的文件:
InputStream in=PropertiesDemo.class.getClassLoader().getResourceAsStream("要读取的文件在bin目录下的相对路径");
19、枚举类
public enum 枚举类名{
枚举项0,枚举项1,枚举项2……;
}
- 所以枚举类都是Enum的子类。
- 枚举类的项必须放在第一行,枚举项其实就是实例对象。
- 枚举类也可以构造方法,但必须是private修饰的。
- 枚举类可以写抽象方法,但是枚举项必须重写。
完~~~ 如果发现有错请在评论区指出,谢谢浏览的大佬 -.-