Java_SE 第二次培训记录
2013-11-15 10:55
375 查看
int i = 9; int k = i++ <==> int k = i; i++; int j = ++i; <==> i++; int k = i; 如果两个操作数中有一个double类型,另一个操作数就会转换为double类型 否则,如果其中一个数是float类型,另一个操作数将会转换为float类型 否则,如果其中以个操作数是long类型,另一个操作数转换为long类型 否则,两个操作数都将被转换为int类型 continue 跳过循环体中剩余的语句而执行下一次循环 只能用于循环结构中 break 直接跳出循环 可用于switch结构和循环结构中 //冒泡排序 public static void bubbleSort(int[] array) { for (int x = 0; x < array.length - 1; x++) // 0 { for (int y = 0; y < array.length - 1 - x; y++) //0 { if (array[y] > array[y + 1]) //0 { int temp = array[y]; array[y] = array[y + 1]; array[y + 1] = temp; } } } } // 选择排序 public static void selectSort(int[] array) { for (int i = 0; i < array.length - 1; i++) { for (int j = i + 1; j < array.length; j++) { if (array[i] > array[j]) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } } } } int[] arr = new int[]{12,11,24,57,63}; //foreach 遍历数组 for(int ele:arr) { System.out.print(ele+" "); } ----------------------------------------------------------------------- 4.3 ------------- 面向对象: 1、没有返回值、和类同名、给属性赋值 2、new对象就是调用了构造方法 对于static修饰的 是类的属性和方法 可以用类名. 调用 加final,代表最后的意思,就是它修饰的变量(属性)值是不可被更改的 定义常量时候字母全部大写 方法重载:方法名相同 参数列表不同 和返回值类型无关 封装: 为了访问和修改私有的属性 利用一对共有的方法getter和setter方法 this指代本类的对象 4.7 ----------- 代码快: 执行顺序是:静态代码快(static{}) 代码快({}) 构造方法(public Dog()) 构造方法中调用其它的构造方法 要用this关键字 并且必须在第一句 public Dog() { this("",1); this.name="dog1"; } public Dog(String name,int health) { } 注意:不能循环调用 this: this()-直接调用构造方法 this.属性 this.方法名 注意:封装:当属性是Boolean类型的话 getter方法的方法名用 一般用 is+属性名 继承(extends): java只能单继承 c++可以多继承 子类默认调用父类构造方法 super(); super和this一样用法 访问修饰符: private 本类中可见 default 同包可见 protected 同包和子类可见 public 一切皆可见 new 子类对象时 已经偷偷构建出父类的对象 也就调用了父类的构造方法 构建子类对象时,父类对象也一同被构建,默认调用无参构造方法 来构建对象 或者 执行里面的逻辑 4.8 ------------------ 方法重载(overload):方法名相同 参数列表不同 和返回值类型无关 方法重写(override):方法名相同 参数列表相同 返回值类型相同(或者是它的子类) 访问权限要大于等于被重写的方法 public void print() 和 public String print() 是重复 不能这么写 抽象类abstract class: 抽象类: 不能实例化 目的就是不让实例化无意义的类 抽象方法:必须存在于抽象类中 没有方法体 必须在子类重写(除非是抽象的子类) final: 修饰类:不能被继承 修饰方法:不能被重写 修饰变量:常量不能被修改 final和abstract不可以同时出现 多态: 多态调用方法时要经过两个过程: 1、编译时过程 看引用所属的类型是什么 看父类是否有这个方法 2、运行时过程 看引用所指的对象是什么 对用儿子的方法 static方法 引用对象去调用 f.show() 其实就是 Father.show() 不用看子类 static: 1、静态方法不能直接调用非静态的方法或者属性 类加载: 静态的成员随着类加载时就已经执行 常见的类加载形式:创建对象,类名. 类就加载一次 父类引用变量指向子类的实例 例: Pet p = new Dog(); 同一个引用类型 不同的对象实例 实现对应 对象的方法 父子关系向上转型,不需要显示转换 如果两个操作数中有一个double类型,另一个操作数就会转换为double类型 否则,如果其中一个数是float类型,另一个操作数将会转换为float类型 否则,如果其中以个操作数是long类型,另一个操作数转换为long类型 否则,两个操作数都将被转换为int类型 ---------------------------------------------------------------- Pet pet = new Dog(); pet.run(); pet类中要有run()方法 父子向下转型,要显示转换 Dog dog = (Dog)pet; dog.run(); pet类中可以没有run()方法 instanceof 运算符: if(pet instanceof Dog//类型或者接口) { Dog dog = (Dog)pet; dog.eat(); } private 方法不可以重写 static 方法不可以重写 属性不可以被重写 4.9 -------------- 接口(interface): 多态:接口的引用变量指向实现类的实例 接口引用变量=实现类的实例 接口:不可实例化 必须实现所有方法(除非是抽象类) 可以实现多个接口 变量都是静态常量 修饰符只能是public 修饰 不写默认就是public 接口中的方法 public abstract 可以省略 默认的 接口中的方法 public static final 可以省略 默认的 可以用 接口名.常量 接口中只有 常量和抽象方法 实现接口同时要实现它的子接口 接口也可以继承接口 可以多继承接口 类可以多实现接口 4.11 -------------------- 异常: System.out.printf("%d/%d=%d",n1,n2,n1/n2); //格式化打印 父类Throwable 子类Error 和 Exception(子类:RuntimeException运行期异常) 1、try..catch(多个)..finally 2、throws Exception 3、throw+异常对象 try catch finally语句中 1、catch中 有return 则 finally中的语句必须执行,之外的语句不执行 2、try 中 有 return 则 finally中的语句也执行,之外的语句不执行 e.priceStackTrace() 比 e.getMessage() 错误信息多 输出的时间要长 参看源代码 重写的方法 不能比被重写的方法范围更大的异常(儿子的异常不能比父亲的大) 常见的异常: ArithmeticException 算术,算法异常 by zero InputMismatchException 输入不匹配参数异常 ArrayIndexOutOfboundsException 数组下标越界异常 NullPointerException 空指针异常 访问null对象 ClassNotFoundException 找不到calss异常 ClassCastException 类型转换异常 IllegalArgumentException 非法参数异常 NumberFormatException 数字格式化异常 String类: //字符串(对象类型) //!!!! //取得参数所对应下标的字符返回 char charAt(int index); //!!!! //把字符串变成字符数组返回 char[] toCharArray(); //把字符数组变成字符串 new String(char[]) String.valueOf(char[]) 遍历数组+" " 拼接字符串 new String(char[] c,int offset,int count) 获取部分数据变成字符串 //!!!! //获取字符串中字符的个数(长度) int length(); //测试字符串是否是空字符串(空字符串不同于null) boolean isEmpty()//???jdk>=6 //取得参数表示下标的字符对应的unicode码值 int codePointAt(int index); //取得参数表示下标之前一位字符的码值 int codePointBefore(int index) //比较字符串出现在字典中的顺序 int compareTo(String otherStr) "a".compareTo("b")//-1 //比较字符串出现的字典顺序(不区分大小写) int compareToIgnoreCase(String otherString) //!!! + //拼接字符串(通常使用+操作来取代concat) String concat(String otherString) "a".concat("b");//"ab" //测试包含参数字符串 boolean contains(String otherString) "ab".contains("a");//true "ab".contains("c");//false //没有containsIgnoreCase,但可以使用其他的机制来完成这个功能 //toLowerCase //toUpperCase //!!! //字符串变大,小写 String toUpperCase(); "a".toUpperCase();//"A" "AB".toUpperCase();//"AB" String toLowerCase(); "AB".toLowerCase();//"ab"; "Ab".toLowerCase();//"ab" //!!!!! equals //测试参数与调用者字符串内容是否相同 boolean contentEquals(String otherString) "a".contentEquals("a");//true "ab".contentEquals("a");//false //多数使用equals,equalsIgnoreCase "a".equals("a");//true "A".equals("a");//false; "A".equalsIgnoreCase("a");//true //把字符数组变成字符串返回 String copyValueOf(char[] chArr); String.copyValueOf(new char[]{'a','b'});//"ab" String.copyValueOf(new char[]{'a','b','c'},1,2);//"bc" //!!!! //以参数字符串开始,startsWith //以参数字符串结尾,endsWith boolean startsWith(String otherString) "abc".startsWith("a");//true "abc".startsWith("abc");//true boolean endsWith(String otherString) "abc".endsWith("abc");//true "abc".endsWith("ab");//false //把字符串赋值到字符数组中 void getChars(int startIndex,int endIndex, char[] charArr,int toStartIndex); //startIndex:表示字符串中开始下标 //endIndex:表示字符串中结束下标(不包含在内) //charArr:目标字符数组(字符串中的字符将要复制到的数组) //toStartIndex :字符数组准备接受第一个字符的下标 String str = "abcdefg"; char[] chArr = new char[3]; str.getChars(1,4,chArr,0); chArr//{'b','c','d'} 注意:String 操作不会改变原来的值 得到的是一个新的字符串 StringBuilder StringBuffer 会改变原来的值 并且是同一个对象 StringBuilder-单线程,快于 StringBuffer,建议使用 StringBuffer--多线程 安全 4.16 File --------------- File方法: canExecute() canRead() canWrite() isHidden() lastModified() length() getFreeSpace() getTotalSpace() getUsableSpace() getName() getParent() getPath() getAbsolutePath() getParentFile() getAbsoluteFile() exists() isFile() isDirectory() delete() deleteOnExit() 虚拟机结束后才删除 createNewFile() mkdir() mkdirs()//父文件夹不存在一同创建 list() listFiles() listFiles(FilenameFilter f) //要建一个类实现FilenameFilter接口,来定义个过滤器 //过滤器中的 返回值表示是否需要:ture需要 false不需要 案例: //过滤的处理方法 public boolean accept(File dir, String name) { // TODO Auto-generated method stub //dir 当前所要列举的目录 // System.out.println("dir==>"+dir); //name 正在被查看的子文件或者子目录 // System.out.println("name==>"+name); if(name.endsWith(".txt")) { return true; } //返回值表示是否需要:ture需要 false不需要 return false; } InputStream/OutputStream FileInputStream FileOutputStream 常用,重点 节点流 ObjecetInputStream ObjectOutputStream 基本数据类型和对象 DataInputStream DataOutputStream 基本数据类型流 BufferedInputStream BufferedOutputStream 重点 封装流 缓存流 Buffered流 readLine()=null //表示没有数据 bw.newLine();//换行 注意:int data = fis.read(byte[]) //data是读数组的长度,个数 4.17 Reader/Writer FileReader FileWriter BufferedReader BufferedWriter LineNumberReader/LineNumberInputStream 可以得到行号,父类是缓存流 BufferedReader getLineNumber(); //得到每一行的行号 4.18 ObjectInputStream 操作的对象要实现序列化 让对象实现 implements Serializable tansient 修饰的属性不被序列化 自动装箱: Integer num = 5; ==》 5=》new Integer(5); ==》Integer num = new Integer(5); 自动拆箱: 直接找到num 然后 取出 Integer里面的值 int 《==》 Integer(JDK1.5以后自动装箱,拆箱) 【int--->Integer】new Integer(int i); Integer.valueOf(int i); 【Integer--->int】Integer i = new Integer(12); i.intValue(); Integer 《==》 String【引用数据类型和字符串相互转换】 【Integer--->String】i.toString(); 【String--->Integer】new Integer(String str); Integer.valueOf(String str); int 《==》 String【基本数据类型和字符串互相转换】 【int--->String】+""; Integer.toString(int i); 【String--->int】Integer.parseInt(String s); ================================================================================ java中的文件是如何描述的? 答:通过File类来描述文件,也可以描述目录。 4.16 流主要分为: 输入流:读取数据 输出流:写出数据 数据在流的传输过程中的表现形式: 字节流:字节输入流InputStream 和 字节输出流OutputStream 字符流:字符输入流Reader 和 字符输出流Writer 学习内容: 了解io流的层次结构, 字节流 FileInputStream 重点: 1、FileInputStream FileOutputStream 2、如何使用上面的两个类实现文件的读写 3、字节数组与字符串的相互转换,以及乱码的处理(能力) 了解: 1、IO流的层次结构 2、File对象及常用的方法 3、获取想要的文件或者目录(过滤器)(能力) 补充: 递归:将一个较大的操作过程分解成多个重复的小过程 在代码中的表现形式:方法本身自己调用自己。 作业: 1、控制台输入两个数:num1 num2 使用递归实现num1的num2次方 2、字符串反转 思路:转化为数组 数组反转 再转换为字符串 3、提供一个目录路径,遍历其子孙目录以及子孙 用递归 4.17 根据流操作的对象性质不同,可以将流分为节点流(底层流)和封装流(上层流) 节点流:直接与保存数据的介质(存数据的,U盘)进行交互的流。 节点流在操作数据时肯定是已字节或者字符的形式 封装流;是基于节点流而封装的上层流。 使用封装流来处理数据时,可能就不会以存字节或者字符的形式来处理 重点: 缓冲流(封装流): BufferedReader BufferedWriter BufferedInputStream BufferedOutputStream 执行效率高。在内存中会预设一个缓冲区。 键盘输入流和输出流(在网络编程时再重点使用再重点讲)PriintWrite 4.18 对象序列化: 实现方式:让对象实现Serializable 接口 使用在哪些地方:1、网络数据传输 2、数据库保存数据 等(以实体对象的形式传输或者保存) 好处:可以实现对象的原子性 保证数据在传输的过程中的一致性 了解:RandomAccesFile 可以随机访问(读和写)文件中莫一部分内容 (注:与文件以及编程工具等字符集编码相关) mode:“r” “rw” seek(long); 设置偏移量,默认是在文件的开始 java中的foreach循环(java1.5以后) 语法:for(元素类型 元素名:数组或者泛型集合){循环体} for(String name//定义一个变量:names) 包装类(封装类) 对于基本数据类型都对应者他们各自的引用数据类型(类) byte Byte short Short int Integer long Long float Float double Double char Character boolean Boolean 两个过程: 装箱:将基本数据类型的值封装成一个引用数据类型,并将改值放入发哦引用类型所指的空间中。 拆箱:取得引用类型所指空间中的值 自动装箱: Integer num = 5; ==》 5=》new Integer(5); ==》Integer num = new Integer(5); 自动拆箱: 直接找到num 然后 取出 Integer里面的值 int 《==》 Integer(JDK1.5以后自动装箱,拆箱) 【int--->Integer】new Integer(int i); Integer.valueOf(int i); 【Integer--->int】Integer i = new Integer(12); i.intValue(); Integer 《==》 String【引用数据类型和字符串相互转换】 【Integer--->String】i.toString(); 【String--->Integer】new Integer(String str); Integer.valueOf(String str); int 《==》 String【基本数据类型和字符串互相转换】 【int--->String】+""; Integer.toString(int i); 【String--->int】Integer.parseInt(String s); 总结: 数值型与字符型转换: 字符串-->数值: 包装类型.parseXXX(); 包装类型.valueOf(string); 数值-->字符串: +“”; toString();//注:引用类型和基本数据类型调用toString()有所不同 集合: 作用:可以用于存储一组数据(类似与数组,但比数组有很大的优点,优点在于可以动态的存储数据,可以自动扩容) 键值对:可以通过键找到对应的值 java中常见的集合: 接口Collection-->常用的子接口有:List Set 接口Map (不是继承与Collection) 每个接口常用的实现类: List: ArrayList(常用) LinkedList Set: HashSet(常用) TreeSet Map: HashMap(常用) TreeMap 特殊的与集合相关的类: Collections(类,不是表示集合,它是在操作集合) 几种常见集合的特点: Collection:可重复,无序 List:可重复,有序 ArrayList:基于数组实现,访问元素的效率比较高 LinkedList:基于链表实现,插入删除效率比较高 Set:不可重复,无序 HashSet: TreeSet:可以实现排序功能 案例: Iterator<Horse> it = horseSet.iterator(); while(it.hasNext()) { // Horse h = (Horse)it.next(); Horse h = it.next(); System.out.println(h.getName()+" * "+h.getAge()); } ArrayList相关方法: add(Object o); add(int index,Object o) get(i); size(); clear(); isEmpty(); remove(int i); remove(Object);//要保证删除的是同一个对象 contains(Object o);//集合中是否包含这个元素 LinkedList相关方法: addFirst(Object o); addLast(Object o); removeFirst(Object o); removeLast(Object o) getFirst(int i); getLast(int i); 泛型:<> 遍历集合常用的方式: for循环 foreach循环 迭代器Iterator Iterator it = set.iterator(); while(it.hasNext()) { Object o = it.next(); System.out.println(o); 迭代器+泛型 } Iterator<Horse> it = horseSet.iterator(); while(it.hasNext()) { //Horse h = (Horse)it.next(); Horse h = it.next(); System.out.println(h.getName()+" * "+h.getAge()); } 集合为什么能够使用迭代器进行遍历? 因为集合都继承或者实现了Iterable接口。 4.19 ------------ Map:是一系列键值对的集合,它不是继承于Collection接口. 特点:键具有唯一性, HashMap相关的方法: put(Key,Value); get(Key); Set set = map.KeySet();//所有键的集合 Collection c = map.Value();//所有值的集合 containsKey(Object o); containsValue(Object o); remove(Object Key); size(); 补充(自定义): 了解 泛型:代表者莫一种类型 我们给它什么类型 此时就表示这种类型 好处:能过使得类中的莫种类型具有一定的弹性 泛型类: 语法:public class 类名<T>{} 泛型算法(方法):一般来说都是静态的方法 语法:public static <T> 返回类型 方法名(参数列表){} //泛型方法 java中的泛型是在表示一种引用数据类型 public static <T extends Comparable> MaxMin<T> getManMin(T[] arr) { if(null == arr || arr.length == 0) { return null; } else { T max = arr[0]; T min = arr[0]; for(int i=0;i<arr.length;i++) { if(max.compareTo(arr[i])<0) { max = arr[i]; } if(min.compareTo(arr[i]) > 0) { min = arr[i]; } } return new MaxMin<T>(max,min); } java.util.Properties(预习) 内部类 inner class: 定义:在一个类中再定义一个类。 分类: 一、静态内部类:static 1、被标识为static的内部类 2、不能访问外部类中的非static成员 3、创建内部类对象:Outer.Inner inner = new Outer.Inner(); 4、静态内部类中既可以定义非静态的成员也可以定义静态成员 二、成员内部类:非static 作为类的一个成员 1、内部类中调用它所在的外部类中的方法: a) 外部类名.this.方法名() b) 创建内部类对象: Outer.Inner inner = new Outer().new Inner(); c) 声明内部类的引用:要么导包 要么Outer.Inner d) 注意:内部类中不能直接定义静态变量和方法 属性可以是static final 三、局部内部类:定义在方法中的类 此类没有修饰苻 1、可以直接访问外部类中的成员变量 2、局部内部类访问其所在方法中的局部变量时,该变量必须是final修饰的 3、定义在方法中的类 可见范围:当前的方法体 四、匿名内部类: 1、没有类名的类 2、语法: Animal dog = new Animal("小黑","23") { @Override public void show() { System.out.println("小黑是条狗"+getName()+" "+getAge()+" "+super.name); } }; dog.show(); 4.22 AWT Swing --------------------- GUI:图形用户接口(界面) Grapfical User Interface AWT:抽象窗口工具集 Abstract Window ToolKit 包含着我们在开发窗口应用程序时所要使用的一系列接口和类 swing 跨平台 java.awt javax.swing java.awt.event 窗口由大量组件(Conponent)组成,使用容器来管理。(容器本身也是组件) 窗口中任何组成部分都是组件 Component(组建 抽象类) | | Container(容器 ) Buttom | | Window(窗口 抽象类) Panel | | Frame Dialog | FileDialog Awt:常用的组建: 容器:Frame(窗口) Panel(面板:不能单独显示) 其他组件:Button Label TextField TextArea RadioButton CheckBox等(注:后期学习了Swing之后,awt中的就很少被使用) 组件的定位: 1、容器的大小以及组件的大小、 2、容器所使用的布局管理器 显示窗口:setVisiable(true) 隐藏窗口:setVisiable(false) 常用的三个布局管理器: BorderLayout FlowLayout GridLayout GardLayout(不常用) GridBagLayout(不常用) Frame:默认布局管理器是BoardLayout Panel:默认布局管理器是 FlowLayout BorderLayout:默认放到容器中间区域(其他区域不指定,就不会显示) FlowLayout: 逐行放,一行满则到下一行,默认居中对齐,默认组件之间的间距为5像素 在同一个窗口中,不同的容器都可以有独立的布局管理器。 相关方法: f.setSize(); f.setLocation(); f.setBackground(Color.READ/new Color(int r,int g,int b)); f.setLayout(null); //取消布局管理器 f.setLayout(new FlowLayout()); f.setVisiziable(boolean); f.setResizeable(true);//不可改变窗口的大小 new FlowLayout();//无参构造,采用默认策略 水平垂直5像素 居中 new FlowLayout(int align//FlowLayout.RIGHT,20,10); new GridLayout(int rows,int clols);//几行 几列 事件:在组件上触发的动作 ,称为一个触发事件 事件监听器:根据触发的不同的事件有多种不同的事件监听器、 作用:监听事件的发生,并给出相应的处理方法 事件源:发生事件的组件 addActionListener(ActionListener a); //ActionListener 接口中定义了按钮被点击的事件处理方法 事件适配器:预定义好的事件监听器接口的实现类。 在swing中: JFrame:最外层的窗口对象 //getContentPane():获得容器区域 //一般这么做 jf.getContentPane().add(b1); //希望窗口关闭的同时结束应用程序 jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //对话框组件 JOptionPane JOptionPane.showConfirmDialog(jf, "确定要退出吗?","警告",JOptionPane.OK_CANCEL_OPTION,JOptionPane.WARNING_MESSAGE); 相关方法: jf.getContentPane().add(b1); //获得容器区域 jf.dispose();//真正的关闭当前窗口 jf.setVisible(false); //窗口隐藏 jt.setEditable(false);//设置文本框不可编辑 jt.setHorizontalAlignment(JTextField.RIGHT); //设置文本水平对齐方式 jpf.setEchoChar('*');//修改密码框的显示符号样式 jrb1.setSelected(true);//设置默认被选中的 jcb.addItem("德国"); //复选框加一个选项 ButtonGroup bg = new ButtonGroup(); JRadioButton jrb1 = new JRadioButton("男"); JRadioButton jrb2 = new JRadioButton("女"); bg.add(jrb1); bg.add(jrb2); 组件: JLabel JButton JTextField JPassworfField JRadioButton //单选按钮 JComboBox //下拉列表框 4.24 Java中一共有23种设计模式。 掌握:工厂,简单工厂,代理模式。 了解: 观察者模式等。 了解:发布-阅读 通常涉及两个组件 物理组件(被观察对象) 观察者组件(观察对象) 被观察的对象的任何状态的改变都会通知观察者调用其相应的处理方法。 在此模式中是松散耦合的。(不是直接调用的方式去执行观察者的方法,而是通过通知 让观察者自己去执行莫个方法) 该模式通常用于事件处理系统中 (例:swing中组件与其对应的监听器) 4.25 线程: 一个任务就是一个程序也是一个进程 一个进程有多个线程 如何创建线程(线程的实现方法有哪几种?): 线程的生命周期: 什么是锁?锁的作用?如何来处理临界资源 进程与线程: 进程:相对于操作系统而言同时运行多个应用程序 线程:相对于应用程序而言同时运行多个代码片段 多任务的操作系统:可以同时运行多个应用程序 多任务:此时执行的多个应用程序相对于一个cpu而言 在同一个时间点上,事实只有一个程序被执行。但由于可能多个程序被排列在队列中等待循环调用。 由于运行速度非常块,我们感觉好像在同时执行。 抢占式: main方法本身就是一个线程,称为主线程 多进程:数据存储空间完全独立,相互影响 多线程:可能共享同一段数据存储空间,可能相互影响 进程之间切换花费开销比较大(空间和时间上) 线程之间切换花费开销比较小(进程于线程想对而言) 线程:主要执行的代码片段在run方法中 run方法:我们称为线程体 Java中线程的实现方式主要有两种: 1、继承Thread类 2、实现runnable 线程如何启动?---》调用run方法 线程对象.start(); 两种实现方式的比较: 1、在语法上,如果使用继承的方式来实现,不便于代码的扩展(因为java在类上是单继承) 线程生命周期经历的状态有: 1.创建 new 2.就绪 .start() 3.运行 真正执行run() 4.阻塞 常见的情况:sleep() wait() I/O输入输出 从阻塞到就绪:时间到 notify()/notifyAll() 等到输入输出完成 5.消亡 run()结束 守护线程: 一般是为其他线程提供服务的线程。当其他线程结束时该线程自动结束。 如何终止线程? 1.stop()过时 不安全 2.使用一个boolean变量来控制线程是否运行 (注:线程一旦终止 则无法再进入就绪队列) 复习: 线程:是一个应用程序中独立的执行莫个事务的代码片段 Thread-》线程对象(run方法:线程体) 线程特点:并发执行。(会在抢) 线程中常用的知识点: 1、线程的生命周期 2、线程让出cpu sleep yield 3、停止线程 4、join 让莫个线程执行完再执行主线程 锁:Synchronized(理论要清楚,简单的编写) Java中提供了锁的机制:好处:在多线程访问同一个资源时,能保证数据资源的一致性,实现 资源同步。 使用关键词:synchronized为对象加锁 一旦莫一个对象被synchronized加锁后,当一个线程访问此对象,其它线程若也要访问这个对象 则他们必须等待第一个线程释放锁之后才能访问。 两种写法: 1、为对象加锁 Synchronized(对象){} 2、方法加锁 public synchronized 返回类型 方法名(参数列表){} //方法当中的资源都会被加锁 wait 和 notify notifyAll需要写在synchronized块中 不然会出现异常(IllegalMonitorStateException) 记住: wait() 进入等待池 会释放对象锁 sleep() 是不会释放持有的对象锁 避免死锁: 1、线程持有锁的时间尽可能短。 2、锁的资源尽可能小 线程同步的方法: 使用synchronized wait() sleep() 什么时候可能会想到使用线程? 使用情况: 1、在程序执行的过程中,有一个独立的行为需要一直被执行 2、同一个行为可能面对多个不同的对象,此时我们可以将该行为封装为一个线程,一个线程就对应一个对象 网络编程: 1、ip地址标识整个网络中的唯一一台计算机 2、端口(port):标识一台计算机中莫一个应用程序 Tcp/Ip协议:Transmission Control Protocol Telent FTP SMTP SNMP ip:由4个8位的二进制数组成,每个数字的范围0-255. ip:网络号+主机号 A:0-127(0.0.0.0主机地址 127.0.0.1本机回环地址,经常被用于做本机测试) 例:10.3.24.88 网络号10.0.0.0 主机号0.3.24.88 B:128-191 例:130.1.28.94 网络号:130.1.0.0 主机号:0.0.28.94 C:192-223 例:192.168.3.29 网络号:192.168.3.0 主机号 0.0.0.29 D:224-239 E:240-247 ...248-255 DNS:域名解析系统 能够将域名地址解析成对应的ip地址 Socket(套接字):ip+port 端口号:0-65535 其中0-1023为系统所保留 常用的端口:http 80 telnet 23 ftp 21 在网络中常见两种数据传输协议: TCP:传输数据有序、安全,有链接协议。 UDP:无序的、不安全,无链接协议。但效率高,比较适合小数据(没有顺序要求)传输 四层:应用 传输 网络 链路 http://127.0.0.1:8888/a/aa.jsp URL:统一资源定位苻 主要由三部分组成:协议+ip(或者ip+端口)+资源路径 相关的类: InetAddress 类描述一个ip地址 无构造方法 单例模式 InetAddress.getByName URL:getProtocol() getHost() getPort() getPath()//资源路径 openStream()//获取输入流对象 读取网页内容 重点: TCP协议下的通信: 主要使用的类:Socket(客户端) ServerSocket(服务器端) 原理(步骤): 1、服务器 创建一个ServerSocket实例 监听一个端口 等待客户端的连接 2、客户端 创建一个Socket实例 -》连接上服务器(需要ip和port) 3、实现通信 能够获得各自的输入输出流对象 UDP协议通信: 主要两个类:DatagramPacket DatagramSocket 这种通信方式下,数据报是通信数据的载体 DatagramPacket 类DatagramPacket 构造方法 这两个方法用于接收数据 public DatagramPacket(byte[] buf, int length) public DatagramPacket(byte[] buf, int offset, int length): 这两个方法用于发送数据 public DatagramPacket(byte[] buf, int length, InetAddress address,int port) public DatagramPacket(byte[] buf, int offset, int length,InetAddress address, int port): 获取数据——获取接收报中的信息 InetAddress getAddress() byte[] getData() int getLength() int getPort() 设置数据——设置发送报中的信息 setAddress(InetAddress iaddr)、setPort(int iport)、 setData(byte[] buf)、setData(byte[] buf, int offset, int length) setLength(int length) 类DatagramSocket 构造方法 public DatagramSocket() public DatagramSocket(int port):在指定的端口通信 public DatagramSocket(int port, InetAddress laddr):在指定的地点运行 这三个方法都将抛出例外SocketException,程序中需要捕获处理。 最主要的方法——发送与接收数据报 public void receive(DatagramPacket p) public void send(DatagramPacket p) 这两个方法都将抛出例外IOException,程序中需要捕获处理。 其他方法 public void connect(InetAddress address, int port):与指定的机器通信 public void disconnect():关闭与指定机器的连接 public void close():关闭Socket -------------------- 补充:Log4j.jar 使用: log4j 是一个日志文件,可以记录代码执行的过程。跟踪代码执行的情况。 Java 三个平台 J2SE J2EE J2ME Oracle ---------- scott connect conn 用法: disconnect disc //断开当前链接 exit //退出数据库 交互式命令 & 可以代替变量,而且该变量在执行的时候,需要用户输入 edit 可以编辑指定的sql脚本 @ start 运行sql脚本 spool 可以将sql*plus屏幕上的内容输入的指定的文件中 用法:spool f:\test1.sql ..........(输入的脚本) spool off 【spool f:\test1.sql ..... spool off】 显示和设置环境变量 1、linesize:设置显示行的宽度,默认是80个字符 2、pagesize:设置每页显示行的数据 用法:set linesize/pagesize 大小(800) 【set linesize 500 / set pagesize 600】 / 重复执行上一条语句的操作 查询表结构 desc tablename select {distinct} *|具体的列名 {as}别名 from 表名 //distinct 删除重复的行 限制查询 select {distinct} *|具体的列名 {as}别名 from 表名 where || 字符串的连接 四则运算(+-*/) 比较运算(= > < >= <= != <>) //!= <> 不等与 空值: is null / is not null 逻辑运算符 and or not // 优先级别 not and or 在sql中有个指定范围的语句: between...and(包括最小值和最大值) 指定范围查询:in 语法:字段名in(值1,值2,值3) 模糊查询:使用like 语句 两种通配符 % //可以匹配任意长度的内容 _ //可以匹配一个长度的内容 语法: 字段名 like(not like) + 字符串 排序 select {distinct} *|具体的列名 {as}别名 from 表名 where 条件 order by 排序字段 asc|desc,排序字段 asc|desc //asc-升序 单行函数: 1、字符函数 大小写函数 upper(‘’) //把小写换成大写 lower(‘’) //把大写变小写 initcap(‘’) //把首字母大写 concat(‘’,‘’) //字符串进行连接 substr(字符串,开始位置,截取的长度) //截取字符串 length() //求字符串的长度 replace('',要换的字符,替换成的字符) //替代 trim() //去除字符串头部和尾部的空格trim(‘’ from ‘’) 默认去除空格 select trim('c' from 'abc' ) from dual; //c右边截取掉 select trim('a' from 'abc' ) from dual; //a左边截取掉 ltrim() rtrim() select rtrim('abc','c') from dual; lpad() //以有对齐方式补充字符型的数据,左边补充特定的字符 rpad() select rpad('abc',15,'**') from dual; instr(字符串,字符) //显示字符所在的字符串的位置 2、数值函数 round()// 四舍五入 select round(78.125,-1) from dual; //第二参数是从小数点开始看 trunc()// 直接截取 mod()// select mod(10,3)from dual; 3、日期函数 sysdate // 显示当前系统时间 dd-mon-year 日期-数字=日期 日期+数字=日期 日期-日期=数字(天数) months_between()//求出给定日期的月数 select months_between(sysdate,'29-4月 -13') from dual; add_months() //得到月份 select add_months(sysdate,1) from dual; next_day() //下一个今天是哪天 select next_day('日期','星期二') from dual; select next_day(sysdate,'星期二') from dual; //当前日期的下个星期二是那个日期 last_day()//这个月的最后一天 select last_day(sysdate) from dual; //得到是个日期 round() select round(sysdate,'month') from dual; trunc() select trunc(sysdate,'month') from dual; 4、转换函数 to_char() //转换成字符串 1、对日期转换 格式:to_char(date,'formate model') to_char(sysdate,'yyyy-mm-dd hh24:mi:ss AM') 年:yyyy 月:mm 日:dd 星期 dy 时:hh 分:mi 秒:ss 英文显示 年:year 月:month(mon) 日:day(dy) 小时:hour 分钟:minute 秒:second 2、对数字进行转换 格式:to_char(number,'format') 9:数字 0:0 ¥ $:美元 L:本地的货币符号 .:小数点 ,:千位符 fm:去除多余的空格或者前导0 to_number():把字符串转换成数字 to_date():转换为日期 to_date('2013-5-3','yyyy/mm/dd') 5、通用函数 nvl(expr1,expr2):将null的值转换成一个实际的值 //nvl(comm,0) nvl2(expr1,expr2,expr3):如果expr1不是null,则返回expr2,是null返回expr3 decode(col/expr,search1,result1,search2,result2,.......): col/expr:列或者是表达式 search1....:用于比较的条件 result:返回的值 //最后一个可以不写search case表达式 case expr/col when expr1 then return1 when expr2 then return2 ................. else ethne end nullif(expr1,expr2):expr1和expr2相同返回空值 不等 返回第一个表达式 coalesce(expr1,expr3....exprn):返回第一个非空表达式 多表查询 select {distinct}*|列名 from 表名1,表名2。。。{where 条件}。。。。。 等值连接 自连接 左右连接 左练级:(+) 在右边 右连接:(+) 在左边 SQL:1999语法 格式:select table.column,table2.column from table[cross join table2] 交叉连接 [natural join table2] 自然连接 自动进行字段的关联 [join table2 using(col)] 直接关联列 [join table2 on(table.col=table2.col)] 自己写连接的条件 左连接(左外连接)和右连接(右外连接) left outer join right join select e.deptno,e.ename,d.dname from emp e left outer join dept d on(e.deptno=d.deptno); //标准语法 select e.deptno,e.ename,d.dname from emp e right outer join dept d on(e.deptno=d.deptno); //标准语法 组函数以及分组统计 组函数: count():求出全部的记录数 max():求出一组中最大的值 min();求出一组中最小的值 avg();求出平均值 sum();求总和 分组统计: group by //select后的字段只能是group by后面的的字段名 //where 后不能出现分组函数 having 分组条件 //having 不能使用组函数的别名 分组的简单原则 注意:分组函数可以使用嵌套,但是在组函数嵌套使用的时候,不能出现分组条件的查询语句 子查询: select * from 表,(select 语句) 别名 select * from 表 where 条件(select 语句) 子查询在操作中分为三类 单列子查询:返回的结果是一列的一个内容 单行子查询:返回多个列,也有可能是一条完整的记录 多行子查询:返回多条记录 注意点:所有的子查询必须在()中编写 子查询中,存在三种查询的操作符 in:指定一个查询的范围 all: >all:比里面最大的要大 <all:比里面最小的要小 any: =any(与in的操作符功能完全相同) >any:比里面最小的值要大 <any:比里面最大的值要小 5.6 ----------- DML: DDL: DCL: 常见的oracle数据类型: 1、字符型: varchar2(n):可变长度的字符串类型,实际字符串的长符不足的时候,不会使用空格进行补充。n<=4000 char(n):固定长度的字符串 2、数值行: number(p,s) p:有效数 s:s>0:精确到小数点右边s位,并四舍五入 s=0:number(p),此时表示的是整数 s<0:精确到小数点左边s位,并且四舍五入 3、日期时间型 date: century year month day hour minutes second 4、lob类型(大对象类型) 主要是存储大对象,最大存储容量4GB clob:用于存储大型的文本数据(备注。。。) blob:用于存储二进制的数据,如图片文件 bfile:作为单独的文件存在的二进制 DML:1、select 2、insert update delete create table xwq_tab as select * from emp; insert: 语法:insert into 表名(字段名称) values(字段名称1的值,。。。) update: 修改全部:update 表名 set 要修改的值=新值,要修改的值=新值 修改局部:update 表名 set 要修改的值=新值,要修改的值=新值 where 修改的条件 delete: delete from 表名 where 条件 oracle 中的事务:保证事务的完整性 回滚:rollback; 提交:commit; 设置回滚点: savepoint 回滚点; rollback to 回滚点; 创建和管理表 --------------- 表的创建: 语法:create table 表名(字段,字段类型[default 默认值],。。。。。) create table 表名 as select(子查询语句)---复制表(表结构+表数据) 子查询 create table emp_xwq as select * from emp where 1=2;(复制表结构) 删除表: drop table 表名 修改表: alert table 表名 add(字段名 字段类型 【defaule】,......) 修改类型和默认值 alter table 表名 modify(字段的名称 列的类型【default】......) 为表重命名 rename 旧表名 to 新表名 alter table 表名 rename column 旧的字段名 to 新的字段名 截断表 truncate table 表名;【注意:操作后不能rollback】 约束:(重点) 约束的分类: 主键约束:唯一+非空 primary key 唯一约束:unique 非空约束:not null 只能在字段后面加 检查约束:check(age between 0 and 100) cheack(sex in('男','女')) 外键约束:foreign key | constraint 约束名 foreign key(外键字段名) references 父表名(主键字段名) on delete cascade; on delete cascade ---强制删除数据不考虑子表的引用 外键约束主要是定义在父表和子表之间的关系,外键要定义在子表上,父表则必须具有主键约束 约束使用方法: 1、字段名类型后+约束 2、最后写 constraint person_pid_key primary key(pid) (正规) 增加约束: alter table 表名 add constraint 字段名 约束 修改约束: alter table 表名 modify (字段名 约束名称) 删除约束: alter table 表名 drop constraint 约束名称; //禁用约束(disable|enable) alter table student disable constraint 约束名字 alter table student disable constraint uk_phone; alter table student enable constraint uk_phone; 查看约束的信息: user_constraints select * from user_constraints; 显示约束的列 user_cons_columns rowid---表示一个文件的物理地址 rownum---伪列 //合并表 merge into xwq1 x1 using xwq2 x2 on(x1.id = x2.id) when matched then update set x1.name = x2.name when not matched then insert values (x2.id,x2.name); //设置列不可用,但磁盘中还存在 alter table tablename set unused column (col,col1....) alter table tablename drop unused column; --创建表空间 create tablespace xwq datafile 'd:\13031\xwq.dbf' size 10m; --创建用户 create user xwq identified by xwq default tablespace xwq; --为用户授权 grant dba to xwq; 5.7 JDBC: ------------- Java数据库连接技术(java database connectivity) 作用:能够实现在java程序中访问数据库,并向数据库发送sql语句,获得执行的结果。 步骤: 1、加载(注册)驱动 2、获得连接 3、获得状态集(发送sql 并执行) 4、获得结果 5、处理结果 6、释放资源(肯定要做的事) Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名","root",""); stmt = conn.createStatement(); / pstmt = conn.prepareStatement(); pstmt.setString(1,"") pstmt.setInt(2,12) /rs = stmt.executeQUery(); rs = stmt.executeQuery(sql); while(rs.next()) { int id = rs.getInt(""); String name = rs.getString(""); } 使用Statement实现对SQL语句的操作: 10w条数据需要插入? SQL语句需要编译10w次 再执行10w次 一共 20w次 使用PreparedStatement实现对SQL语句的操作: 10w条数据 编译1次 执行10w次 1、建表 2、创建实体类(与数据库中的表一一对应) 3、编DAO接口以及实现类 //DAO能过实现java中的对象与表中的记录相互转换 事物:是一个原子操作单元,不可分割。 原子性 一致性 持久行 隔离性 单例: 单例模式:在系统中一个类的实例始终只有一个。 两种方式:饿汉式 懒汉式 方法一、 private String name; private int age; private static Singleton single = new Singleton(); private Singleton(){}; public static Singleton getSingle() { return single; } 方法二、 private static Singleton single = null; private Singleton(){}; public static Singleton getSingel() { if(null == single) { single = new Singleton(); } return single; } 工厂模式: 简单工厂模式: 反射: 常见的反射的方式: Class.forName(String):可以反射到该字符串对应的类。创建该类的对象 xxx.class: 相关代码: Class c = Class.forName(""); Object o = c.newInstance();// 动态的创建类对象 Method[] methods = c.getDeclareMethods(); for(Method m:methods) { if(m.getName().equals("setName") { m.invoke(o,"",""); //o调用m这个方法 后面是可变长参数 也是这个m方法的参数 } } java中类加载器: 主要有三种:系统类加载器 扩展类加载器 应用类记载器(AppClassLoader) properties:属性文件(配置文件) 通常会应用在对环境的配置上。 存放数据的形式:以键值对的形式存储。 ThreadLocal:不是一个线程,只是当前线程的一个线程变量 通常被用于解决多线程并发的问题 分层: 1、显示层:窗口-接受用户数据/呈现数据给用户 2、服务层: 3、数据访问层: 4、数据层:实体类 String... agrs //可变长参数 底层用数组去处理 alt+shift+j //加注释 ---- 元数据 数据库元数据:DatabaseMetaData dbmd = conn.getMetaData(); 结果集元数据:DatabaseMetaData dbmd = conn.getMetaData(); Connection类 如下二个方法: 方法: Statement createStatement() throws SQLException; Statement createStatement(int resultSetType,int resultSetConcurrency) resultSetType值 TYPE_FORWARD_ONLY 结果集不可滚动 (默认类型 ) TYPE_SCROLL_INSENSITIVE 结果集可滚动,不反映数据库的变化 TYPE_SCROLL_SENSITIVE 结果集可滚动,反映数据库的变化 resultSetConcurrency值 CONCUR_READ_ONLY 不能用结果集更新数据 (默认类型 ) CONCUR_UPDATABLE 能用结果集更新数据 ---- mysql命令: ------------- mysql -u root show databases drop database + 数据库名 create database + 数据库名 user jdbc; create table dog( id int not null primary key auto_increment, name varchar(20) not null unique, age int not null); //插入一行数据 insert into dog(id,name,age) values (1,'dog1','23'); //插入多行数据 insert into dog(name,age) values('dog2','22'),('dog3','34'); //查数据 select *from dog; //更新数据 update dog set name='abc' where id=1; //删除数据 delete from dog where id=1; truncate table dog; // 可以让id回滚到1开始 mysql 时间类型 date time datetime timestamp Timestamp tt = rs.getTimestamp(); new Date(tt.getTime()); //得到年月日 时分秒 limit: select * from student limit 2,3; //从第2条数据往后读3条 在数据库导入脚本sql source /home/soft01/aa.sql; 导出数据库中的表 在终端(不要进入mysql) mysqldump -u root -p 数据库名 >/home/soft01/aa.sql set character_set_results=utf8; //设置数据库字符编号 ============================================================================= -------补充--------- System.exit(0); //退出虚拟机 0正常退出 1异常退出 方法 void的返回类型的方法 return可加 可不加 swith(整型/字符/枚举/字符串(jdk7.0) static方法不能重写 其实就是类.变量名 不看子类 垃圾回收机制; 1、引用计数 2、停止复制 3、增量收集(分代收集与Train算法) Object中的 == 和 equal 是相同的 比较都是对象的内存地址 String中是不同的 String中equal是重写了Object方法 比较的是内容 创建日期: Calendar c = new GregorianCalendar(); c.get(Calendar.YEAR); c.get(Calendar.MONTH);//从0开始的 c.get(Calendar.DAY_OF_MONTH); c.get(Calendar.HOUR_OF_DAY); c.get(Calendar.MINUTE); c.get(Calendar.SECOND); //判断数组是否为空、 if(null != files && files.length>0)//不同的两种情况 int[] nums=null和int[] nums={}; 数据比较时:null放在前面,常量和变量比较 常量放在前面。 递归调用: //根据你提供的数实现累加的运算,并返还结果 //一般来说在递归调用中会存在一个终止条件 public static int getResult(int num) { if(num == 1) { return 1; } return num+getResult(num-1); } UTF 格式 可以快速本地化 a)垃圾回收 Java:垃圾不需要程序员自己回收,jvm会根据数据的使用来决定是否回收垃圾 长期不可达的数据会被作为垃圾回收 枚举:本身是一种类型。 可以用来列举一组值。 //往mysql数据库插入时间 1、可以用new() 2、 //数据库出入 年月日 pstmt.setDate(1,new java.sql.Date(news.getDate().getTime())) //数据库插入 年月日 时分秒 pstmt.setTimestamp(1,new java.sql.TimeStamp(news.getDate().getTime())) -------概念---------- 变量:是计算机内存的一段空间,用于存放数据。 属性是类的静态特征 方法是类的动态行为 类是对象的抽象,模型 对象是类的实例 封装:属性私有化 继承:代码复用,避免冗余 is-a关系 抽象类:用abstract修饰的类就是抽象类 特点:不能实例化,不能创建对象,可以有抽象方法,继承抽象类的类要么也是抽象类, 要么重写抽象方法 接口:特点定义的都是常量和抽象方法 异常:编译期异常,运行期异常 错误:是程序员无法通过代码解决的问题 //实例化的对象getClass()得到Class HttpServletRequest 方法的参数类型 Method m = action.getClass().getMethod(method, HttpServletRequest.class,HttpServletRequest.class); Log4j: ------- A:使用log4j实现类 B:使用commons-logging接口(log4j是该接口的一个实现) 方法一:只需要一个log4j实现类jar包 import org.apache.log4j.Logger; Logger logger = Logger.getLogger(LogTest1.class); //将该类中的信息以以下各种优先级别输出 logger.debug("debug信息。。。。。。"); logger.info("info信息。。。。。。。"); logger.warn("warn信息。。。。。"); logger.error("error信息。。。。。。。"); logger.fatal("fatal信息。。。。。"); 方法二:只需要一个接口包和一个实现类jar包 import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; Log logger = LogFactory.getLog(LogTest2.class); logger.debug("debug信息。。。。。。"); logger.info("info信息。。。。。。。"); logger.warn("warn信息。。。。。"); logger.error("error信息。。。。。。。"); logger.fatal("fatal信息。。。。。"); 注意:不同的包想要实现不同的优先级别,可以自定义包的优先级别 log4j.logger.con.itany.log1 =warn 绘图: -------------- // 1、随机生成4个字符【0-9|a-z|A-Z】 Random random = new Random(); String code=""; for(int i=0;i<4;i++) { int num = random.nextInt(62); //n<10---->[0-9] if(num < 10) { code+=num; } else if(num < 36) { code+=(char)(num-10+'a'); } else { code+=(char)(num-36+'A'); } } System.out.println(code); //2、将这4个字符绘制成一张图片 HttpSession session = req.getSession(); session.setAttribute("code",code); //创建img对象长度68px 高度 28px BufferedImage image = new BufferedImage(68,28,BufferedImage.TYPE_INT_RGB); //获取绘图所用的画笔 Graphics graphics = image.getGraphics(); //设置画笔的颜色 graphics.setColor(Color.yellow); //绘制边框 graphics.fillRect(2, 2, 64, 24); //设置字体 graphics.setFont(new Font("Courier New",Font.ITALIC|Font.BOLD,20)); //遍历这4个字符,依次绘制图片 for(int i=0;i<code.length();i++) { String str = code.substring(i, i+1); //给文字设置颜色 graphics.setColor(Color.black); //绘制图片 graphics.drawString(str, 16*i+5, 20); } resp.setContentType("image/jpeg"); //获取输入输出流 OutputStream out = resp.getOutputStream(); //在该输出流上创建一个图像编码器 JPEGImageEncoder encode = JPEGCodec.createJPEGEncoder(out); //将图像写入到流中 encode.encode(image); //刷新到客户端 out.flush(); //关闭输出流 out.close(); <script type="text/javascript"> function changePic() { //vat timestamp = new Date().getTime(); document.getElementById("pic").src = "codeServlet?t="+Math.random(); } </script> <body> <img id="pic" src="${pageContext.request.contextPath }/codeServlet" title="看不清楚,换一张" style="cursor: pointer" onclick="changePic()"/> </body>
相关文章推荐
- 黑马程序员Java培训、Android培训-Java 学习过程记录_面向对象上
- Java_SE培训笔记
- 黑马程序员Java培训、Android培训-Java 学习过程记录_面向对象下2
- 参加某培训机构Java培训记录(一)
- 海外组09夏令营java第二次培训
- Java第二次记录
- 参加某培训机构Java培训记录(八)
- java培训第二次课后笔记
- 参加某培训机构Java培训记录(二)
- 黑马程序员Java培训、Android培训-Java 学习过程记录_面向对象上2
- 黑马程序员Java培训、Android培训-Java 学习过程记录_面向对象下
- 黑马程序员Java培训、Android培训_Java 学习过程记录_开发前奏
- 黑马程序员Java培训、Android培训-Java 学习过程记录_面向对象下3
- 参加某培训机构Java培训记录(七)
- 参加某培训机构Java培训记录(十)
- 参加某培训机构Java培训记录(九)
- 黑马程序员Java培训、Android培训-Java 学习过程记录_多线程
- 黑马程序员Java培训、Android培训-Java 学习过程记录_多线程3
- 黑马程序员Java培训、Android培训-Java 学习过程记录_JavaAPI-1
- 黑马程序员Java培训、Android培训-Java 学习过程记录_JavaAPI