JAVA复习
访问控制修饰符:
类别 | 范围 | 使用对象 |
---|---|---|
default | 同一包内可见 | 类、接口、变量、方法 |
private | 同一类内可见 | 不能修饰类 |
public | 对所有类可见 | 类、接口、变量、方法 |
protected | 同一包内和所有子类可见 | 变量、方法、不能修饰类(外部类) |
访问控制和继承:
- 父类的Public方法在子类中也必须是public
- 父类中的protected方法在子类中要么为protected,要么为public
- 父类声明为private方法,不能被继承
网络编程:
-
利用socket建立连接的过程:
- 连接建立后,通过使用I/O流进行通信,每一个socket有一个输出流和输入流,客户端的输出流连接到服务端的输入流,客户端的输入流连接到服务器端的输出流
-
例子:
-
package com.xidian.网络编程; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class ClientDemo { public static void main(String[] args) throws Exception { Socket sc= new Socket("localhost",12345); /* * 通过Socket对象,获取到输出流对象,向服务端写数据 */ OutputStream os = sc.getOutputStream(); String str="nihao,I am the Client!"; os.write(str.getBytes()); //client 用Socket对象 接收 server 的信息 InputStream is = sc.getInputStream(); byte[] bys= new byte[1024]; int len = is.read(bys); String str2 = new String(bys,0,len); System.out.println(str2); is.close(); os.close(); sc.close(); } } package com.xidian.网络编程; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class ServerDemo { public static void main(String[] args) throws Exception { //创建服务端socket对象 ServerSocket server = new ServerSocket(12345); //通过Socket#accept 一直监听客户端的信息 Socket accept = server.accept(); //通过accept对象获得输入流对象,来读取来自客户端的信息 InputStream is = accept.getInputStream(); byte[] bys= new byte[1024]; int len = is.read(bys); //将读取到的字节转换成String类型 String str= new String(bys,0,len); System.out.println(str); //服务端向客户端发送确认消息 OutputStream os = accept.getOutputStream(); os.write("Hello,I am the server.I accept the message!".getBytes()); //ServerSocket的对象是不需要关闭的 //要关闭的是IO流对象,以及accept用于监听的对象 os.close(); is.close(); accept.close(); } }
-
JDBC:
-
例子
-
package com.runoob.test; import java.sql.*; public class MySQLDemo { // JDBC 驱动名及数据库 URL static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB"; // 数据库的用户名与密码,需要根据自己的设置 static final String USER = "root"; static final String PASS = "123456"; public static void main(String[] args) { Connection conn = null; Statement stmt = null; try{ // 注册 JDBC 驱动 Class.forName("com.mysql.jdbc.Driver"); // 打开链接 System.out.println("连接数据库..."); conn = DriverManager.getConnection(DB_URL,USER,PASS); // 执行查询 System.out.println(" 实例化Statement对象..."); stmt = conn.createStatement(); String sql; sql = "SELECT id, name, url FROM websites"; ResultSet rs = stmt.executeQuery(sql); // 展开结果集数据库 while(rs.next()){ // 通过字段检索 int id = rs.getInt("id"); String name = rs.getString("name"); String url = rs.getString("url"); // 输出数据 System.out.print("ID: " + id); System.out.print(", 站点名称: " + name); System.out.print(", 站点 URL: " + url); System.out.print(" "); } // 完成后关闭 rs.close(); stmt.close(); conn.close(); }catch(SQLException se){ // 处理 JDBC 错误 se.printStackTrace(); }catch(Exception e){ // 处理 Class.forName 错误 e.printStackTrace(); }finally{ // 关闭资源 try{ if(stmt!=null) stmt.close(); }catch(SQLException se2){ }// 什么都不做 try{ if(conn!=null) conn.close(); }catch(SQLException se){ se.printStackTrace(); } } System.out.println("Goodbye!"); } }
-
JAVA泛型:
-
泛型类
-
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型 //在实例化泛型类时,必须指定T的具体类型 public class Generic<T>{ //key这个成员变量的类型为T,T的类型由外部指定 private T key; public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定 this.key = key; } public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定 return key; } }
//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型 //传入的实参类型需与泛型的类型参数类型相同,即为Integer. Generic<Integer> genericInteger = new Generic<Integer>(123456); //传入的实参类型需与泛型的类型参数类型相同,即为String. Generic<String> genericString = new Generic<String>("key_vlaue"); Log.d("泛型测试","key is " + genericInteger.getKey()); Log.d("泛型测试","key is " + genericString.getKey());
1、泛型类的参数只能是类类型,不能是简单类型
2、可以不传入泛型类型实参,这个时候参数可以是任意类型
-
-
泛型接口
-
与泛型类类似:
public interface Generator<T>{ public T next(); }
-
实现泛型接口的类,未传入泛型实参
-
/** * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中 * 即:class FruitGenerator<T> implements Generator<T>{ * 如果不声明泛型,如:class FruitGenerator implements Generator<T>,编译器会报错:"Unknown class" */ class FruitGenerator<T> implements Generator<T>{ @Override public T next() { return null; } }
实现泛型接口的类,传入泛型实参
public class FruitGenerator implements Generator<String> { private String[] fruits = new String[]{"Apple", "Banana", "Pear"}; @Override public String next() { Random rand = new Random(); return fruits[rand.nextInt(3)]; } }
-
-
泛型方法
文件操作:
-
文件的读
-
以行为单位读取文件
-
public static List<String> readFileByLines(String filePath){ File file = new File(filePath); if(!file.exists() || !file.isFile()){ return null; } List<String> content = new ArrayList<String>(); try { FileInputStream fileInputStream = new FileInputStream(file); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "GBK"); BufferedReader reader = new BufferedReader(inputStreamReader); String lineContent = ""; while ((lineContent = reader.readLine()) != null) { content.add(lineContent); System.out.println(lineContent); } fileInputStream.close(); inputStreamReader.close(); reader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return content; }
-
-
文件的写
-
通过FileWriter将字符串写入文件
public static void writeFileByFileWriter(String filePath, String content) throws IOException{ File file = new File(filePath); synchronized (file) { FileWriter fw = new FileWriter(filePath); fw.write(content); fw.close(); } }
-
Exception和Error的区别:
- Exception用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。
- Error用于标记严重错误,合理的应用程序不应该去try/catch这种错误,绝大多数的错误都是非正常的,根本不应该出现。
- Error和RuntimeException及其子类都是未检查的异常(unchecked exception),而所有的其他的Exception类都是检查了的异常。
- checked exceptions:通常是从一个可以恢复的程序中跑出来的,并且最好能够从这种异常中使用程序恢复,例如,FileNotFoundException,ParseException等。
- unchecked exceptions:通常是如果一切正常的话不该发生的异常,但是的确发生了。比如,ArrayIndexOutOfBoundException,ClassCastException等。
GUI
-
常用SWING组件
- JFrame
- void setTitle(String title)
- void setSize(int width,int height)
- void setResizable(boolean resizable)
- void setVisible(boolean b)
- void setDefaultCloseOperation(int operation)
- void dispose()
- void repaint()
- JButton
- void setText(String Text)
- String getText()
- void setBackground(color bg)
- Color getBackground()
- void setEnabled(boolean b)
- void setVisible(boolean b) //设置按钮是否可见
- JLabel
- void setText(String text)
- String getText()
- void setIcon(Icon icon)
- void setHorizontalAlignment(int alignment) //设置文本的对齐方式
- void setVisible(boolean b)
- JTextField
- void setText(String text)
- String getText()
- void setHorizontalAlignment(int alignment)
- void setEditable(boolean b)
- void setEnabled(boolean enabled) //设置启用(禁用)文本框
- void setVisible(boolean) //设置文本框是否可见
- JPanel
- setBackground(Color bg)
- void setLayout(LayoutManager mgr)
- Component add(Component comp)
- Component add(Component comp,int index) //将指定的组件添加到面板的指定位置上
- void remove(Component comp)
- void removeALL() //从面板中移除所有的组件
- void repaint()
- JFrame
-
布局管理器
- FlowLayout
- BorderLayout
- GridLayout
-
程序编写步骤:
1、在构造函数中完成组件的初始化以及构建 2、设置JFrame的布局 3、将初始化完成的组件添加到布局中的相应位置 4、设置JFrame的基本属性,包括setSize、setDefaultCloseOperation、setVisible public class test extends JFrame implements ActionListener{ private JTextField jtf1; private JButton jb1; public test(){ jtf1=new JTextField("文本框"); jb1=new JButton("按钮"); this.setLayout(new BorderLayout()); //网格布局 this.setLayout(new GridLayout(1,2)); //流式布局 this.setLayout(new FlowLayout()); this.add(jtf1,BorderLayout.CENTER); this.add(jb1,BorderLayout.SOUTH); this.setSize(400,300); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); jb1.addActionListener(this);//为组件添加事件监听机制 } public static void main(String[] args){ new test(); } @override public void actionPerformed(ActionEvent e){ JButton jb=(JButton)e.getSouce(); if(jb==jb1){ //触发相应的操作 } } }
多线程
-
生命周期
-
三种创建线程的方法
-
实现Runnable接口
package com.xidain; import java.util.Date; public class test1 implements Runnable{ public static void main(String[] args) { Thread t=new Thread(new test1()); //继承Runnable接口,实例化变量的方法 t.start(); } @Override public void run() { // TODO 自动生成的方法存根 for(;;){ try { Thread.sleep(1000); // t.sleep(1000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } System.out.println(new Date().toString()); } } }
-
继承Thread类本身
package com.xidain.火车票售卖; public class 多窗口卖火车票 { public static void main(String[] args) { MyThread mt1= new MyThread("窗口1"); MyThread mt2= new MyThread("窗口2"); MyThread mt3= new MyThread("窗口3"); MyThread mt4= new MyThread("窗口4"); mt1.start(); mt2.start(); mt3.start(); mt4.start(); } } package com.xidain.火车票售卖; public class MyThread extends Thread{ static int ticket=100; public MyThread(String name){ super(name); } @Override public void run() { while(true){ synchronized(MyThread.class){ if(ticket<1){ break; } try { Thread.sleep(50); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } System.out.println(getName()+"正在卖第"+ticket--+"张票"); } } } }
-
通过Callable和Future创建线程
package com.xidian; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableThreadTest implements Callable<Integer> { public static void main(String[] args) { CallableThreadTest ctt = new CallableThreadTest(); FutureTask<Integer> ft = new FutureTask<>(ctt); for(int i = 0;i < 100;i++) { System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i); if(i==20) { new Thread(ft,"有返回值的线程").start(); } } try { System.out.println("子线程的返回值:"+ft.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } @Override public Integer call() throws Exception { int i = 0; for(;i<100;i++) { System.out.println(Thread.currentThread().getName()+" "+i); } return i; } }
-
使用Thread类的方式创建多线程时,当需要访问当前线程的时候,无需使用Thread.currentThread()方法,直接使用this即可获得当前线程
-
接口
-
特性:
- 接口中的每一个方法是隐式抽象的,接口中的方法会被隐式的指定为public abstract
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量(用private修饰会报编译错误)
- 接口中的方法不能再接口中实现,只能由实现接口的类来实现接口中的方法
-
抽象类和接口的区别
- 抽象类的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行
- 抽象类中的数据成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
- 接口中不能含有静态代码块以及静态方法,而抽象类是可以有静态代码块和静态方法的
- 一个类只能继承一个抽象类,但是能实现多个接口
-
接口的定义
public interface NameOfInterface{ //任何类型final,static字段 //抽象方法 } //例子: interface Animal { public void eat(); public void travel(); }
声明接口或者方法的时候不需要加abstract关键字,因为是隐式抽象的,接口中的方法都是公有的
-
接口的实现
- 当类实现接口的时候,必须实现其中的所有方法,否则类必须声明为抽象类
-
接口的继承
- 和类的继承类似
- 允许多继承
-
标记接口
- 没有任何方法和属性的接口
- 目的
- 建立一个公共的父接口
- 向一个类添加数据类型
关键字
-
assert
- 表示断言功能
- 语法:
- assert<boolean 表达式> :如果<boolean表达式>为true,程序继续执行;如果为false,则程序抛出AssertionError,并终止执行
- assert<boolean表达式>:<错误信息表达式>:<Boolean表达式>为true,程序继续执行;如果为false,程序抛出java.lang.AssertionError,并输入<错误信息表达式
-
-
static
-
不能再静态方法中访问非静态变量;可以在静态方法中访问静态的成员变量。可以在非静态方法中访问静态的成员变量:因为静态方法是可以直接用类名来调用,而非静态成员变量是在创建对象实例时才为变量分配内存和初始化变量值。
-
不能再静态方法中使用this关键字
-
修饰代码块:静态代码块的作用是完成一些初始化的工作。首先执行静态代码块,然后执行构造方法。静态代码块在类被加载的时候执行,而构造方法是在生成对象的时候执行;要想调用某个类来生成对象,首先需要将类加载到JAVA虚拟机上,然后由JVM加载这个类来生成对象
-
构造方法和静态代码块的执行顺序:静态代码块只会在类被加载的时候执行一次,而每次生成一个对象的时候都会调用类的构造方法。如果继承体系中既有构造方法,又有静态代码块,首先执行最顶层类的静态代码块,一直执行到最底层的静态代码块,然后再去执行最顶层类的构造函数,一直执行到最底层的构造函数。
-
当一个类和别的类存在继承关系的时候,初始化的顺序是:
父类的静态变量>子类的静态变量>子类的main方法>父类的非静态变量>父类的构造器>子类的非静态变量>子类的构造方法对于一个类来说,类中的非静态变量的初始化的顺序先于构造函数的执行顺序
-
-
多态:
- 在运行的时候才会知道引用变量所指向的具体实例对象
- 指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法
- 三个必要条件
- 继承
- 重写
- 向上转型:父类引用指向子类对象
- 实现形式
- 继承
- 当子类重写父类的方法被调用时,只有对象继承链中的最末端的方法才会被调用
- 接口
- 继承
集合
-
遍历集合的三种方式
List<String> list=new ArrayList<string>(); list.add("hello");
-
利用foreach
for(String str:list){ Sysout(str); }
-
将链表变为数组相关的内容进行遍历
String[] strArray=new String[list.size()]; list.toArray(strArray); for(int i=0;i<strArray.length;i++){ sysout(StrArray[i]); }
-
利用迭代器
Iterator<String> ite=list.iterator(); while(ite.hasNext()){ sysout(itr.next()); }
-
-
遍历Map的方法
-
二次取值
for(String key:map.KeySet()){ //Set<String> ketSet=map.keySet();返回一个键所组成的集合 sysout(key+map.get(key)); }
-
通过Map.entrySet使用迭代器遍历key和value
Iterator<Map.Entry<String,String>> it=map.entrySet().iterator(); while(it.hasNext()){ Map.Entry<String,String> entry=it.next(); sysout(entry.getKey()+entry.getValue()); }
-
通过Map.entrySet遍历key和value
for(Map.Entry<String,String> entry:map.entrySet()){ sysout(entry.getKey()+entry.getValue()); }
-
-
集合类的继承关系
- 三个子接口
- Set
- 不允许包含相同的元素,add()相同元素的时候,会返回false,且新元素不会被加入
- List
- 元素有序,并且是可重复的
- 默认按照集合的添加顺序设置元素的索引
- Queue
- Set
- 三个子接口
-
map继承关系图
- 同一个Map对象的任何两个key通过equals方法比较从事返回false