JAVA 基础加强学习笔记
一、面向对象
(一)继承
1.继承的好处:
(1) 提高了代码的复用性。
(2) 让类与类之间产生了关系,提供了另一个特征多态的前提。
注意: 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super(); 如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数。 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。
2.final特点:
(1) 这个关键字是一个修饰符,可以修饰类,方法,变量。
(2) 被final修饰的类是一个最终类,不可以被继承。
(3) 被final修饰的方法是一个最终方法,不可以被覆盖。
(4) 被final修饰的变量是一个常量,只能赋值一次。
3.抽象类的特点:
(1) 抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
(2) 抽象方法只定义方法声明,并不定义方法实现。
(3) 抽象类不可以被创建对象(实例化)。
(4) 只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。
(5),抽象类只能单继承。
4.抽象类的细节:
(1) 抽象类中是否有构造函数?有,用于给子类对象进行初始化。
(2) 抽象类中是否可以定义非抽象方法? 可以。其实,抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。
(3) 抽象关键字abstract和哪些不可以共存?final , private , static
(4) 抽象类中可不可以不定义抽象方法?可以。抽象方法目的仅仅为了不让该类创建对象。
5.接 口:
如果一个抽象类中的所有方法都是抽象的,且这个抽象类中的数据成员都是final的常量,那么,这个抽象类实际上就是一个接口,即一种特殊的抽象类。对于实现该接口的子类来说,接口不提供任何实现,接口是抽象方法和常量值定义的集合。
接口具有以下特点:
(1) 接口中的常量默认为public static final,而且也只能是public static final
(2) 接口中只能定义抽象方法,这些方法默认为public abstract,而且也只能是public abstract
(3) 接口可以继承其他接口,而且可以添加新的属性和抽象方法
(4) 在接口中声明方法时不能使用static、final、private等修饰符
(5) Java不允许类的多继承,但允许接口的多继承
(6) 不允许创建接口的实例,但允许定义接口类型的引用变量,改变量要引用实现了该接口的类的实例
(7) 一个类只能继承另外一个类,但能同时实现多个接口,并且重写方法必须显示声明为public
抽象类和接口的区别:
(1) 抽象类只能被继承,而且只能单继承。 接口需要被实现,而且可以多实现。
(2) 抽象类中可以定义非抽象方法,子类可以直接继承使用。 接口中的方法都是抽象方法,需要子类去实现。
(3) 抽象类使用的是 is a 关系。 接口使用的 like a 关系。
(4) 抽象类的成员修饰符可以自定义。
接口中的成员修饰符是固定的。全都是public的。
(二)多 态
多态是面向对象特征之一,构造函数本身就具备多态性,某一种事物有不同的具体的体现。 体现:父类引用或者接口的引用指向了自己的子类对象。
//Animal a = new Cat();
多态的好处:提高了程序的扩展性。
多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。(前期不能使用后期产生的功能,即访问的局限性)
多态的前提:
1:必须要有关系,比如继承、或者实现。
2:通常会有覆盖操作。
(三)匿名内部类
匿名内部类是没有名字的内部类。就是内部类的简化形式。一般只用一次就可以用
这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。
匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。
匿名内部类的使用场景:
当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。 其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。
二、多线程
线程的两种创建方式
(一)创建线程的第一种方式:
继承Thread ,由子类复写run方法。
步骤:
1,定义类继承Thread类;
2,目的是复写run方法,将要让线程运行的代码都存储到run方法中;
3,通过创建Thread类的子类对象,创建线程对象;
4,调用线程的start方法,开启线程,并执行run方法。
线程状态:
1新建:start()
2运行:具备执行资格,同时具备执行权;
3休眠:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格; 临时
4阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;
5消亡:stop()
例子:
package com.OpenWealth.ZSY; import java.io.*;
import java.net.*; public class TCPServer{ @SuppressWarnings("resource")
public static void main(String[] args) throws Exception{ ServerSocket ss=null;
ss=new ServerSocket(8866);
while(true){ try { Socket soc=ss.accept(); new MyPicServerThread(soc).start();//开启服务端接受图片的线程 } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} /***
* 实现了多用户并发上传图片的服务端
* @author 支胜勇
*
*/
public static class MyPicServerThread extends Thread{ private Socket soc=null; public MyPicServerThread(Socket _soc){
this.soc=_soc;
} @Override
public void run() {
// TODO Auto-generated method stub
String clientIp=soc.getInetAddress().getHostAddress();
try { System.out.println(clientIp+"已连接!"); InputStream in=soc.getInputStream(); FileOutputStream fos=new FileOutputStream("E:\\TcpTest.png"); byte[] buff=new byte[1024]; int len=0; while((len=in.read(buff))!=-1){ fos.write(buff,0,len);
} OutputStream out=soc.getOutputStream(); out.write("图片上传成功!".getBytes()); fos.close(); soc.close(); } catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException("客户端"+clientIp+"上传失败");
} }
}
}
(二)创建线程的第二种方式:
实现一个接口Runnable。
步骤:
1,定义类实现Runnable接口。
2,覆盖接口中的run方法(用于封装线程要运行的代码)。
3,通过Thread类创建线程对象;
4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。 为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
如:Ticket t = new Ticket();
直接创建Ticket对象,并不是创建线程对象。
因为创建对象只能通过new Thread类,或者new Thread类的子类才可以。 所以最终想要创建线程。既然没有了Thread类的子类,就只能用Thread类。
Thread t1 = new Thread(t); //创建线程。
只要将t作为Thread类的构造函数的实际参数传入即可完成线程对象和t之间的关联
为什么要将t传给Thread类的构造函数呢?其实就是为了明确线程要运行的代码run方法。
例子:
package com.OpenWealth.ZSY; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.io.*;
public class TCPClientSocket { public static void main(String args[]) throws Exception{ BufferedReader buff=new BufferedReader(new InputStreamReader(System.in)); //同时上传多张图片
while(true){
String imgUrl=buff.readLine();
new Thread(new MyUpLoadPicClient(imgUrl,"localhost",8866)).start();
} } /**
* 实现了同时上传多张图片的客户端;可以上传多种格式的图片
* @author 支胜勇
*
*/
public static class MyUpLoadPicClient implements Runnable{ private File imgFile; private String ip; private int port; private Socket soc; private List<String> extensList=null; private OutputStream out;
private FileInputStream fis; /***
* 初始化构造方法
* @param imgUrl
* @param ip:服务器IP地址
* @param port:服务器端口
* @throws Exception
*/
public MyUpLoadPicClient(String imgUrl,String ip,int port) throws Exception{ this.imgFile=new File(imgUrl);
this.ip=ip;
this.port=port; extensList=new ArrayList<String>();
extensList.add(".jpg");
extensList.add(".png");
extensList.add(".gif");
extensList.add(".jpeg");
extensList.add(".bmp"); } public boolean isImg(){ if(!imgFile.exists()){//||!imgFile.isFile()
System.out.println("图片不存在,请重新上传!");
return false;
} if(!imgFile.isFile()){//||!imgFile.isFile()
System.out.println("不是图片文件,请重新上传!");
return false;
} String extenName=imgFile.getName().substring(imgFile.getName().lastIndexOf(".")).toLowerCase();
if(!extensList.contains(extenName)){ System.out.println("请上传jpg,png,gif,bmp,jpeg格式的图片");
return false;
} if(imgFile.length()>1024*1024*5){
System.out.println("图片过大,请上传5m以内的图片!");
return false;
} try { fis=new FileInputStream(imgFile); } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
} /***
* 执行向服务器上传图片的代码
*/
@Override
public void run() {
// TODO Auto-generated method stub
if(!isImg()){
return;
}else{
try {
this.soc=new Socket(this.ip,this.port);
out=soc.getOutputStream();
byte[] buff=new byte[1024];
int len=0;
while( (len=fis.read(buff)) != -1 ){ out.write(buff,0,len);
}
soc.shutdownOutput();//告诉服务器上传结束 InputStream in=soc.getInputStream(); byte[] bufIn=new byte[1024]; int num=in.read(bufIn); System.out.println(new String(bufIn,0,num)); fis.close();
out.close();
soc.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
}
}
(三)多线程安全问题的原因:
通过图解:发现一个线程在执行多条语句时,并运算同一个数据时,在执行过程中,其他线程参与进来,并操作了这个数据。导致到了错误数据的产生。
涉及到两个因素:
1,多个线程在操作共享数据。
2,有多条语句对共享数据进行运算。
原因:这多条语句,在某一个时刻被一个线程执行时,还没有执行完,就被其他线程执行了。
解决安全问题的原理: 只要将操作共享数据的语句在某一时段让一个线程执行完,在执行过程中,其他线程不能进来执行就可以解决这个问题。
如何进行多句操作共享数据代码的封装呢?
java中提供了一个解决方式:就是同步代码块。
格式:
synchronized(对象) { // 任意对象都可以。这个对象就是锁。
需要被同步的代码; }
Synchronized(自己的会写得出)
wait和sleep区别:
分析这两个方法:从执行权和锁上来分析:
wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的notify或者notifyAll来唤醒。
sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)。
wait:线程会释放执行权,而且线程会释放锁。
Sleep:线程会释放执行权,但不是不释放锁。
三、JDK1.5新特性
(一)Collection在jdk1.5以后,有了一个父接口Iterable,这个接口的出现的将iterator方法进行抽取,提高了扩展性。
(二)增强for循环:
foreach语句,foreach简化了迭代器。
格式:// 增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器
for( 元素类型 变量名 : Collection集合 & 数组 ) { „ }
高级for循环和传统for循环的区别:
高级for循环在使用时,必须要明确被遍历的目标。这个目标,可以是Collection集合或者数组,如果遍历Collection集合,在遍历过程中还需要对元素进行操作,比如删除,需要使用迭代器。
如果遍历数组,还需要对数组元素进行操作,建议用传统for循环因为可以定义角标通过角标操作元素。如果只为遍历获取,可以简化成高级for循环,它的出现为了简化书写。 高级for循环可以遍历map集合吗?不可以。但是可以将map转成set后再使用foreach语句。
1)、作用:对存储对象的容器进行迭代: 数组 collection map
2)、增强for循环迭代数组:
String [] arr = {"a", "b", "c"};//数组的静态定义方式,只试用于数组首次定义的时候
for(String s : arr) { System.out.println(s); }
3)、单列集合 Collection:
List list = new ArrayList(); list.add("aaa"); // 增强for循环, 没有使用泛型的集合能不能使用增强for循环迭代?能 for(Object obj : list) { String s = (String) obj; System.out.println(s); }
4)、双列集合 Map:
package com.ItHeima.WeekAct; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; public class Test5 {
public static void main(String[] args){ Map<String, String> map = new HashMap<String, String>(); map.put("a", "aaa"); // 传统方式
Set entrys = map.entrySet();
// 1.获得所有的键值对Entry对象
Iterator iter = entrys.iterator(); // 2.迭代出所有的entry
while(iter.hasNext()) { Map.Entry entry = (Entry) iter.next(); String key = (String) entry.getKey(); // 分别获得key和value String value = (String) entry.getValue(); System.out.println(key + "=" + value); } // 增强for循环迭代:原则上map集合是无法使用增强for循环来迭代的,因为增强for循环只能针对实现了Iterable接口的集合进行迭代;Iterable是jdk5中新定义的接口,就一个方法iterator方法,只有实现了Iterable接口的类,才能保证一定有iterator方法,java有这样的限定是因为增强for循环内部还是用迭代器实现的,而实际上,我们可以通过某种方式来使用增强for循环。
for(Object obj : map.entrySet()) { Map.Entry entry = (Entry) obj; // obj 依次表示Entry System.out.println(entry.getKey() + "=" + entry.getValue()); }
//5)、集合迭代注意问题:在迭代集合的过程中,不能对集合进行增删操作(会报并发访问异常);可以用迭代器的方法进行操作(子类listIterator:有增删的方法)。
//6)、增强for循环注意问题:在使用增强for循环时,不能对元素进行赋值;
int[] arr = {1,2,3}; for(int num : arr) { num = 0; //不能改变数组的值 } System.out.println(arr[1]); //
}
}
}
(三)可变参数(...)
用到函数的参数上,当要操作的同一个类型元素个数不确定的时候,可是用这个方式,这个参数可以接受任意个数的同一类型的数据。 和以前接收数组不一样的是:
以前定义数组类型,需要先创建一个数组对象,再将这个数组对象作为参数传递给函数。现在,直接将数组中的元素作为参数传递即可。底层其实是将这些元素进行数组的封装,而这个封装动作,是在底层完成的,被隐藏了。所以简化了用户的书写,少了调用者定义数组的动作。
如果在参数列表中使用了可变参数,可变参数必须定义在参数列表结尾(也就是必须是最后一个参数,否则编译会失败。)。
如果要获取多个int数的和呢?可以使用将多个int数封装到数组中,直接对数组求和即可。
(四)静态导入
导入了类中的所有静态成员,简化静态成员的书写。
import static java.util.Collections.*; //导入了Collections类中的所有静态成员
(五)枚举
关键字 enum
问题:对象的某个属性的值不能是任意的,必须为固定的一组取值其中的某一个; 解决办法: 1)、在setGrade方法中做判断,不符合格式要求就抛出异常; 2)、直接限定用户的选择,通过自定义类模拟枚举的方式来限定用户的输入,写一个Grade类,私有构造函数,对外提供5个静态的常量表示类的实例; 3)、jdk5中新定义了枚举类型,专门用于解决此类问题;
4)、枚举就是一个特殊的java类,可以定义属性、方法、构造函数、实现接口、继承类;
自动拆装箱:java中数据类型分为两种 : 基本数据类型 引用数据类型(对象)
在 java程序中所有的数据都需要当做对象来处理,针对8种基本数据类型提供了包装类,如下:
int --> Integer byte --> Byte short --> Short long --> Long char --> Character
例子:
package com.OpenWealth.Traffic; /***
* 关于方向的枚举类
* @author 支胜勇
*
*/
public enum Direction { EAST{ @Override
public Direction reverse() {
// TODO Auto-generated method stub
return WEST;
} @Override
public Direction positive() {
// TODO Auto-generated method stub
return EAST;
} @Override
public Direction leftSide() {
// TODO Auto-generated method stub
return SOUTH;
} @Override
public Direction rightSide() {
// TODO Auto-generated method stub
return NORTH;
} },
SOUTH{ @Override
public Direction reverse() {
// TODO Auto-generated method stub
return SOUTH;
} @Override
public Direction positive() {
// TODO Auto-generated method stub
return NORTH;
} @Override
public Direction leftSide() {
// TODO Auto-generated method stub
return WEST;
} @Override
public Direction rightSide() {
// TODO Auto-generated method stub
return EAST;
} }
,WEST{ @Override
public Direction reverse() {
// TODO Auto-generated method stub
return WEST;
} @Override
public Direction positive() {
// TODO Auto-generated method stub
return EAST;
} @Override
public Direction leftSide() {
// TODO Auto-generated method stub
return NORTH;
} @Override
public Direction rightSide() {
// TODO Auto-generated method stub
return SOUTH;
} },NORTH{ @Override
public Direction reverse() {
// TODO Auto-generated method stub
return NORTH;
} @Override
public Direction positive() {
// TODO Auto-generated method stub
return SOUTH;
} @Override
public Direction leftSide() {
// TODO Auto-generated method stub
return EAST;
} @Override
public Direction rightSide() {
// TODO Auto-generated method stub
return WEST;
}
}; /**
* 该方向的反方向
* @return
*/
public abstract Direction reverse(); /**
* 该方向的正方向
* @return
*/
public abstract Direction positive(); /**
* 该方向的左面
* @return
*/
public abstract Direction leftSide(); /**
* 该方向的右面
* @return
*/
public abstract Direction rightSide(); }
四、高新技术
(一)反射
反射技术:其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节
码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员。简单说:反射技术可以对一个类进行解剖。 反射的好处:大大的增强了程序的扩展性。 反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。
获取这个Class对象,有三种方式:
1:通过每个对象都具备的方法getClass来获取。弊端:必须要创建该类对象,才可以调用getClass方法。
2:每一个数据类型(基本数据类型和引用数据类型)都有一个静态的属性class。弊端:必须要先明确该类。
前两种方式不利于程序的扩展,因为都需要在程序使用具体的类来完成。
3:使用Class类中的方法,静态的forName方法。
指定什么类名,就获取什么类字节码文件对象,这种方式的扩展性最强,只要将类名的字符串传入即可。
// 1. 根据给定的类名来获得 用于类加载
String classname = "cn.itcast.reflect.Person";// 来自配置文件
Class clazz = Class.forName(classname);// 此对象代表Person.class
// 2. 如果拿到了对象,不知道是什么类型 用于获得对象的类型
Object obj = new Person();
Class clazz1 = obj.getClass();// 获得对象具体的类型
// 3. 如果是明确地获得某个类的Class对象 主要用于传参 Class clazz2 = Person.class;
//反射的用法:
//1)、需要获得java类的各个组成部分,首先需要获得类的Class对象,获得Class对象的三种方式:
Class.forName(classname) //用于做类加载
obj.getClass() //用于获得对象的类型 类名.class 用于获得指定的类型,传参用
//2)、反射类的成员方法:
Class clazz = Person.class;
Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2}); method.invoke();
//3)、反射类的构造函数:
Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2,...}) con.newInstance(params...)
//4)、反射类的属性:
Field field = clazz.getField(fieldName); field.setAccessible(true); field.setObject(value);
获取了字节码文件对象后,最终都需要创建指定类的对象:
创建对象的两种方式(其实就是对象在进行实例化时的初始化方式):
1,调用空参数的构造函数:使用了Class类中的newInstance()方法。
2,调用带参数的构造函数:先要获取指定参数列表的构造函数对象,然后通过该构造函数的对象的newInstance(实际参数) 进行对象的初始化。
综上所述,第二种方式,必须要先明确具体的构造函数的参数类型,不便于扩展。所以一般情况下,被反射的类,内部通常都会提供一个公有的空参数的构造函数。
// 如何生成获取到字节码文件对象的实例对象。
Class clazz = Class.forName("cn.itcast.bean.Person"); //类加载
// 直接获得指定的类型
clazz = Person.class;
// 根据对象获得类型
Object obj = new Person("zhangsan", 19);
clazz = obj.getClass();
Object obj = clazz.newInstance(); //该实例化对象的方法调用就是指定类中的空参数构造函数,给创建对象进行初始化。当指定类中没有空参数构造函数时,该如何创建该类对象呢?请看method_2();
public static void method_2() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
}
//既然类中没有空参数的构造函数,那么只有获取指定参数的构造函数,用该函数来进行实例化。
//获取一个带参数的构造器。
Constructor constructor = clazz.getConstructor(String.class, int.class); //想要对对象进行初始化,使用构造器的方法newInstance();
Object obj = constructor.newInstance("zhagnsan",30); //获取所有构造器。
Constructor[] constructors = clazz.getConstructors(); //只包含公共的
constructors = clazz.getDeclaredConstructors();//包含私有的
for(Constructor con : constructors) {
System.out.println(con);
} //反射指定类中的方法: //获取类中所有的方法。
public static void method_1() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
Method[] methods = clazz.getMethods(); //获取的是该类中的公有方法和父类中的公有方法。
}
methods = clazz.getDeclaredMethods(); //获取本类中的方法,包含私有方法。 for(Method method : methods) { System.out.println(method); } }
//获取指定方法;
public static void method_2() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person"); //获取指定名称的方法。
}
Method method = clazz.getMethod("show", int.class, String.class);
//想要运行指定方法,当然是方法对象最清楚,为了让方法运行,调用方法对象的invoke方法即可,但是方法运行必须要明确所属的对象和具体的实际参数。 Object obj = clazz.newInstance();
method.invoke(obj, 39, "hehehe"); //执行一个方法 }
//想要运行私有方法。
public static void method_3() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person"); //想要获取私有方法。必须用getDeclearMethod();
}
Method method = clazz.getDeclaredMethod("method", null);
// 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。 method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。 }
//反射静态方法。
public static void method_4() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
Method method = clazz.getMethod("function", null);
method.invoke(null, null);
}
JAVA 基础加强学习笔记的更多相关文章
- java基础知识学习笔记
本文知识点以js为参照.对比分析得出笔记.JavaScript之所以叫JavaScript是打算借助java推广自己.虽然都是开发语言,但JavaScript一开始主要运行在 客户端,而java主要运 ...
- Java基础加强学习笔记(二)
一.反射的基础Class类 1.如何得到各个字节码对应的实例对象 (1)类名.class,例如 System.class (2)对象.getClass(),例如 new Data().getClass ...
- 异常处理——毕向东Java基础教程学习笔记
1.异常:就是程序运行过程中出现的不正常情况. 异常的由来:问题本身也是日常生活中一个具体的事物,也可以通过java类的形式进行描述,并封装成对象. 其实 ...
- JAVA 基础知识学习笔记 名称解释
Java ee: IDE: itegrity development environment 集成开发环境 JMS: java Message Service java 信息服务 JM ...
- java基础(个人学习笔记) A
1. 声明long类型的变量 需要在数值的末尾+l/L.(不加L的话,貌似默认就是int型了.当给long赋值一个超过int范围的值的时候,会出问题.) 2. package java_ ...
- Java基础知识学习笔记(一)
理解面向对象: Java纯粹的面向对象的程序设计语言,主要表现为Java完全支持面向对象的三个基本特征:继承.封装.多态. Java程序的最小单位是类,类代表客观世界中具有某种特征的一类事物,这些类可 ...
- 匿名内部类--毕向东java基础教程学习笔记
1.匿名内部类其实就是内部类的简写形式. 2.定义匿名内部类的前提: 该内部类必须继承一个类,或者实现一个接口. 3.匿名内部类的格式:new 父类名或接口名(){定义子类内容:} 4.其实匿名内部类 ...
- 内部类--毕向东Java基础教程学习笔记
内部类的访问规则 1. 内部类可以直接访问外部类的成员,包括私有. 之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 ...
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
随机推荐
- Spring3.0 AOP 详解
一.什么是 AOP. AOP(Aspect Orient Programming),也就是面向切面编程.可以这样理解,面向对象编程(OOP)是从静态角度考虑程序结构,面向切面编程(AOP)是从动态角度 ...
- linux杂谈(十八):DNS服务器的配置(一)
原文地址: http://blog.chinaunix.net/uid-29622064-id-4242123.html 1.DNS服务器简介 域名系统(英文:Domain Name System,縮 ...
- CDOJ 483 Data Structure Problem DFS
Data Structure Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/proble ...
- [MODx] 2. Install some useful packages into ur MODx
1. The package we might need: 2. Install the package: Select Installer Download Extras Install the p ...
- JUnit中测试异常抛出的方法
最近在做TWU关于TDD的作业,对JUnit中测试异常抛出的方法进行了一些学习和思考. 在进行单元测试的时候有的时候需要测试某一方法是否抛出了正确的异常.例如,我有一个方法,里面对一个List进行读取 ...
- Java内部类的自我理解
本文借鉴网络上多位大牛的博客和文章.感谢各位不知名人士的分享. 一.什么事内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的成员,而且依附于外部类而存在的.内部类能够为静态,可用p ...
- 使用命令xrandr设置当前系统的显示分辨率及显示的旋转脚本
/********************************************************************* * Author : Samson * Date ...
- Mysql分表教程
一般来说,当我们的数据库的数据超过了100w记录的时候就应该考虑分表或者分区了,这次我来详细说说分表的一些方法.目前我所知道的方法都是MYISAM的,INNODB如何做分表并且保留事务和外键,我还不是 ...
- 元数据标签Embed
关于Embed外部资源的使用方法总结 Flex软件中经常需要使用一些外部的资源,如图片.声音.SWF或字体,虽然你也可以在软件运行的时候引入和载入,但是也可能经常需要直接将这些资源编译(Compile ...
- MHA手动切换 原创1(主故障)
MHA提供了3种方式用于实现故障转移,分别自动故障转移,需要启用MHA监控: 在无监控的情况下的手动故障转移以及基于在线手动切换. 三种方式可以应对MySQL主从故障的任意场景.本文主要描述在无监控的 ...