内部类
基础
java中可以将一个类定义在另一个类里面或者方法中,这样的类称为内部类。分为:成员内部类、局部内部类、匿名内部类、静态内部类。
一个java文件中可以定义多个类,但是只能有一个使用public修饰,且这个类必须和文件名相同。
成员内部类
最普通的内部类,将一个类定义在另一个类的内部。
class A{
private static int b=10;
private int a = 0;
public A(int a) {
this.a = a;
}
class B{ //内部类
public void Bway() {
System.out.println("Bway");
System.out.println(a);
System.out.println(b);
}
}
}
1.成员内部类可以无条件的访问外部类的成员属性和方法(private也可以)。
2.若成员内部类与外部类成员属性方法发生冲突时,内部类中优先调用内部类,访问方式
(外部类.this.成员变量)(外部类.this.成员方法)
3.外部类访问内部类成员时,需要先实例内部类对象。(new B().方法())
4.在另一个类中调用内部类成员,必须先实例外部类对象,再通过外部类对象实例内部类对象。
(A a = new A(); A.B b = a.new B();)
局部内部类
局部内部类是定义在一个方法内或者一个作用域里面的类。
与成员内部类的区别在于局部内部类的访问权限仅在方法内或者作用域内。
局部内部类不能用public、protected、private 以及 static 修饰符的,只能用final修饰内部类。
class A{
public A(){
}
public void Away(){
class B{ //局部内部类
int age =0;
}
B b = new B();
b.age=10;
}
}
匿名内部类
最常用的内部类,没有名字,定义在其他类方法中的类。
把定义子类、重写父类的方法、创建子类对象,合成一步完成
new A(){
public void Away(){
//重写父类的方法
}
};
静态内部类
静态内部类也是定义在另一个类里面的类,前面多了一个static关键字。
静态内部类是不需要外部类的,可以不用实例化外部类。
静态内部类不能使用外部类中非static的成员变量或者方法。
public class demo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Outter.Inner inner = new Outter.Inner();
}
}
class Outter {
public Outter() {
}
static class Inner {
public Inner() {
}
}
}
集合
与数组的区别
长度:集合可变;数组固定
内容:集合只能引用类型;数组可以基本类型,可以引用类型。
元素:集合可以存储不同类型(一般一种),数组只能存储同一种类型。
Collection接口:接口的接口,单列集合的接口
******** list接口:元素按照先后顺序保存,可重复,有序
**************** LinkedList:接口实现类,底层链表,没有同步,线程不安全
**************** ArrayList:接口实现类,底层数组,没有同步,线程不安全
**************** Vector:接口实现类,底层数组,同步,线程安全
******** set接口:内部排序,不可重复
**************** HashSet:使用hash表存储,底层数组,没有同步,线程不安全
************************* LinkedHashSet:底层链表,有序,不可重复,没有同步,线程不安全
**************** TreeSet: 底层二叉树,最底层TreeMap,自动排序、不可重复、没有同步、线程不安全
Map接口:键值对集合,双列集合的接口
******** Hashtable:接口实现类,同步,线程安全
******** HashMap:接口实现类,没有同步,线程不安全
**************** LinkedHashMap:双向链表与哈希表实现,有序,没有同步,线程不安全
******** TreeMap:红黑数对所有的key进行排序、没有同步,线程不安全
HashMap可以将null设为键,也可以设为值。
Hashtable不可以将null设为键,也不可以设为值。
反射
定义
java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为反射。
必须先要获取到该类的字节码文件对象。解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象
用法
遇到某个类的某个成员变量、方法是私有的或者有权限问题,就可以用反射机制获取私有成员或方法。
类的加载
1).对于任何一个类,当程序中第一次使用这个类时(第一次创建对象、第一次调用这个类中静态成员) JVM会先加载这个类的class文件,并在"方法区"创建一个"Class对象",这个对象中会存储这个类的内部的一些信息:构造方法、成员属性、成员方法…。
2).之后再使用这个类的时候,JVM就不会再去找这个类的class文件了,直接通过之前创建的"Class对象"就可以获取这个类的内部信息,并创建这个类的对象。
3).对于任何一个类,在"方法区"中,都会有,而且只有一个这个类的"Class对象"。
Class对象的初始化时机
1).当一个类第一次被创建对象时;
2).当第一次访问这个类中的静态成员(静态属性、静态方法)时;
3).使用"反射"获取一个类的Class对象时;【今天学习的】
4).当第一使用这个类的"子类"时;
名词
1).Class:类
2).Constructor:构造
3).Method:方法
4).Filed:字段(成员属性或者成员变量)
5).instance:实例
6).invoke:执行
获取Class的方法
package reflection;
/**
* 获取Class对象的三种方式
* 1 Object ——> getClass();
* 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
* 3 通过Class类的静态方法:forName(String className)(常用)
*/
public class reflection{
public static void main(String[] args) {
//第一种方式获取Class对象
Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
Class stuClass = stu1.getClass();//获取Class对象
System.out.println(stuClass.getName());
//第二种方式获取Class对象
Class stuClass2 = Student.class;
System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
//第三种方式获取Class对象
try {
Class stuClass3 = Class.forName("reflection.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
异常
分类
Error:是程序中无法处理的错误,表示运行应用程序中出现了严重的错误。
Exception:程序本身可以捕获并且可以处理的异常。
异常的处理
抛出异常:throw,throws (throw在方法内使用抛出,throws在方法上进行声明使用)
捕获异常:try,catch,finally
try{
可能出现的异常的代码
}catch(异常类型 变量名){
catch中异常类型必须是所有可能出现异常类型的父类
处理异常一般打印异常信息
syso(变量名);
变量名.printStackTrace();
}finally{
关闭资源的代码
如果关闭资源的代码也可能出现异常
直接用try..catch包括即可
}
网络编程
网络编程的目的就是直接或间接地通过网络协议与其他计算机进行通信。在Java中包含网络编程地各种类,通过创建这些类的对象,调用相应的方法,就可以进行网络应用程序的编写。ServerSocket 是服务端、Socket是客户端。
ServerSocket 构造方法
ServerSocket():无参构造方法。
ServerSocket(int port):创建绑定到特定端口的服务器套接字。
ServerSocket(int port,int backlog):使用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口。
ServerSocket(int port,int backlog,InetAddress bindAddr):使用指定的端口、监听 backlog 和要绑定到本地的 IP 地址创建服务器
ServerSocket 的常用方法
Server accept():监听并接收到此套接字的连接。
void bind(SocketAddress endpoint):将 ServerSocket 绑定到指定地址(IP 地址和端口号)。
void close():关闭此套接字。
InetAddress getInetAddress():返回此服务器套接字的本地地址。
int getLocalPort():返回此套接字监听的端口。
SocketAddress getLocalSoclcetAddress():返回此套接字绑定的端口的地址,如果尚未绑定则返回 null。
int getReceiveBufferSize():获取此 ServerSocket 的 SO_RCVBUF 选项的值,该值是从 ServerSocket 接收的套接字的建议缓冲区大小
Socket 的构造方法
Socket():无参构造方法。
Socket(InetAddress address,int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口。
Soclcet(InetAddress address,int port,InetAddress localAddr,int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。
Socket(String host,int port):创建一个流套接字并将其连接到指定主机上的指定端口。
Socket(String host,int port,InetAddress localAddr,int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。Socket 会通过调用 bind() 函数来绑定提供的本地地址及端口。
address 指的是远程地址,port 指的是远程端口,localAddr 指的是要将套接字绑定到的本地地址,localPort 指的是要将套接字绑定到的本地端口
Socket 的常用方法
void bind(SocketAddress bindpoint):将套接字绑定到本地地址。
void close():关闭此套接字。
void connect(SocketAddress endpoint):将此套接字连接到服务器。
InetAddress getInetAddress():返回套接字的连接地址。
InetAddress getLocalAddress():获取套接字绑定的本地地址。
InputStream getInputStream():返回此套接字的输入流。
OutputStream getOutputStream():返回此套接字的输出流。
SocketAddress getLocalSocketAddress():返回此套接字绑定的端点地址,如果尚未绑定则返回 null。
SocketAddress getRemoteSocketAddress():返回此套接字的连接的端点地址,如果尚未连接则返回 null。
int getLoacalPort():返回此套接字绑定的本地端口。
intgetPort():返回此套接字连接的远程端口。
/**
* 服务器端
*/
public class Server {
public static void main(String[] args) {
//5.创建ServerSocket、Socket、OutputStream、InputStream以及端口号并初始化
ServerSocket serverSocket = null;
Socket socket = null;
OutputStream out = null;
InputStream in = null;
int port = 5000;
try {
//6.开启服务器并接收客户端发送的数据
serverSocket = new ServerSocket(port);//创建服务器套接字
System.out.println("服务器开启,等待连接...");
socket = serverSocket.accept();//获得连接
//接收客户端发送的内容
in = socket.getInputStream();
byte[] b = new byte[1024];
int len = in.read(b);
System.out.println("客户端发送的内容为:" + new String(b,0,len));
//7.使用输出流对象将信息返回给客户端
out = socket.getOutputStream();
out.write("我是服务器端".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//8.关闭流对象、ServerSocket对象以及Socket对象
try {
in.close();
out.close();
serverSocket.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
//1.定义 Socket 对象、OutputStream 对象和一个 InputStream 对象并完成初始化
Socket socket = null;
OutputStream out = null;
InputStream in = null;
//定义服务器端的 IP 地址和端口号
String serverIP = "127.0.0.1";//服务器端 IP 地址
int port = 5000;//服务器端端口号
try {
//2.建立与服务器端的连接并将数据发送到服务器端
socket = new Socket(serverIP, port);//建立连接
out = socket.getOutputStream();//发送数据
out.write("我是客户端数据".getBytes());
Thread.sleep(1000);
//3.从输入流中读出服务器的反馈信息并输出到控制台
byte[] b = new byte[1024];
in = socket.getInputStream();
int len = in.read(b);
System.out.println("服务器端的反馈为:" + new String(b, 0, len));
} catch (Exception e) {
e.printStackTrace();
} finally {
//4.关闭流及 Socket 对象
try {
in.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}