该博客的内容是在看了《head first java》之后总结的一些知识点,是针对我个人的不足总结的知识点,我写博客还是newer,希望大神们多多指教。需要注意的是这篇内容的标号和《head first java》中的章节标号不是一致的。
我曾经在一家公司实习的时候,学习的是C#。虽然都是C类语言,但其实它和JAVA的语法之类的更为匹配一些,当时初学的时候就范了一个错误:
class Dog{
String name;
Dog(String na){
name = na;
}
public void setName(String na){
name = na;
}
public String getName(){
return name;
}
}
public class DogTest{
public static void main(String[] args){
Dog[] dog = new Dog[7];
}
}
就像买东西的时候一般都是从口袋里面拿出钱包,再从钱包里面拿出钱。这个钱包就相当于一个引用,但是如果你钱包里面没钱,即使你有钱包也买不到东西(当然,要是老板同意让你拿钱包抵押,那是另外一回事了。。。)。所以 Dog[] dog = new Dog[7];这句代码只相当于你得到了钱包,但是不幸的是钱包里面并目前钱(即对象),所以需要放点钱进去 dog[0] = new Dog(“man”);
C++和java都是面向对象的,但是呢,我个人觉得真正的面向对象是JAVA。虽然大学四年都在和C++打交道,但是连《C++primer》都没看过的我来说,很多知识点是懵的。BUT,我还是先来整理一下关于JAVA的好啦。
需要注意的是:在java中类的成员变量默认为default ,但是在C++中默认为private。
修饰符权限表格如下:
访问权限 | 类 | 同一个包 | 子类 | 其它包 |
---|---|---|---|---|
public | ∨ | ∨ | ∨ | ∨ |
protected | ∨ | ∨ | ∨ | × |
default | ∨ | ∨ | × | × |
private | ∨ | × | × | × |
同时还有类的其它两个修饰符abstract (修饰的类只声明方法,并不实现)、final(修饰的类不能被继承)
局部变量是某个方法的参数或者内部需要时候才声明的变量,这个时候局部声明的变量必须初始化才能使用,但是类中的实例变量不需要在声明的时候初始化。Eg:
class Test{
String name;
public void go(){
String test;
name = name + "right"; //可以通过
test = test + "wrong";//this is wrong!!!必须初始化,因为局部变量没有默认值。
}
}
毕竟我大学四年搬运的代码都是C++的,所以还是需要对比一下两者的不同。JAVA中已经木有了指针的这个概念,其实java中的引用在某些地方是可以替代C++中的指针的作用的。
C++中创建对象
1. Test test;//在栈中
2. Test* test = new Test();
delete(test);//分配的内存在堆中,因为C++中木有GC,所以这种创建对象的方式需要手动删除对象
class Test{
String name;
}
JAVA中创建对象的方式:
Test test = new Test();//分配的内存是在托管堆中,因此并不需要手动删除对象。test是对托管堆中对象的引用。
System.out.println(false & (1/0 == 0));//这句话会抛出异常,因为除数不能为零
System.out.println(false && (1/0 == 0));//这句话会打印出false
Note:这两句话的不同只在于运算符的不同,所以这说明:&运算符会判断左右两边所有条件,但是&&运算符如果前者能决定结果,那么后面的就可以不用判断了。
可以参考java学习之多态,这篇文章写得比《head first java》中清楚得多,毕竟我觉得《head first java》这本书的中文版翻译还是存在很多问题的。总结来说呢,java多态需要注意以下几点:
1. 覆盖属于多态,但是函数重载(不能只改变返回类型)不属于多态。
2. 多态==晚绑定,因为多态是一种运行期的行为,不是编译期的行为
3. 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如:
class Animal{
String name;
public void eat(){
//eat food;
}
}
class Cat extends Animal{
public void makeNoise(){
//make cat noise;
}
public void eat(){
//Cat eat;
}
}
class Dog extends Animal{
public void eat(){
//Dog eat;
}
}
//main
class Test{
public static void main(String[] args){
//向上类型转换
Cat cat = new Cat();
Animal animal = cat;
animal.eat();//right,eat()函数在animal类中也存在,但是 调用的是Cat的eat()函数。
animal.makeNoise();//wrong ,makeNoise()不存在父类中
//向下类型转换
Animal animal = new Cat();
animal.makeNoise();//wrong,makeNoise()在animal父类中不存在。
Cat cat = (Cat)animal;
cat.eat();
cat.makeNoise();//right,调用cat中的makeNoise()函数。
}
}
总结就是:可以用父类代表子类。
关于构造器,主要有以下几点:
1. 在创建新对象的时候,所以继承下来的构造函数都会执行,也就是父类的构造函数都会执行一遍。
2. 某个类的构造函数若修饰符是private,那么代表这个类不能被实例化。
3. 使用this()来从某个构造函数调用同一类的另外一个构造函数,this()只能用在构造函数中,且必须是第一行语句,super()(对父类构造函数的调用)与this()不能兼得。例如 :
class Cat extends Animal{
Color color;
public Cat(){
this(Color.red);//对该类中的下一个构造函数进行调用
}
public Cat(Color c){
super("Cat");//对父类构造函数的调用
color = c
}
}
关于垃圾收集器,java虚拟机的GC机制可以自动回收托管堆中的对象,至于进行回收的算法,那是另外一件事情啦。
1.
pubic class FOO{
public static final int FOO_X = 25;
}
2.
public class FOO{
public static final int FOO_X;
static{
FOO_X = (int)Math.random();
}
}
因为有些时候想把基本数据类型当做对象来处理,就需要对其进行包装,解包。Java5.0之后就加入了autoboxing
//无autoboxing
public void doNum(){
ArrayList listNum = new ArrayList();
listNum.add(new Integer(3));//不能直接加入3,得先转为对象
Integer one = (Integer)listNum.get(0);//返回Object类型,转为Integer类
int intOne = one.intValue();
}
//有autoboxing
public void doNum(){
ArrayList listNum = new ArrayList();
listNum.add(3);//直接加入3,编译器自动装包
int one = listNum.get(0);//编译器自动完成解包
Question: 当每个按钮执行不同工作时,要如何对多个不同的按钮分别取得事件?
Answer: 内部类!!内部类可以外部类的所有方法和变量。内部类的实例一定会绑定在外部类的实例上。
内部类与外部类的关系如下:
监听GUI事件:
Notice:非静态内部类的实例必须通过外部类的实例才能获得,但是对于静态的内部类不需要外部类的实例就可以调用,但是静态内部类只能调用外部类的静态变量。
Question:当你在编写GUI程序的时候,突然发现你需要实现一个ActionListener的类的实例,但是你发现你没有任何该类的实例,之前也没有写个该类,那你该怎么做呢?
Answer:一是在程序中实现内部类,二是当场创建出匿名的内部类。如下:
public class test{
public static void main(String[] args){
JFrame frame = new JFrame();
JButton button = new JButton("click");
frame.getContentPane().add(button);
// button.addActionListener(quitListener);//通常是传入一个内部类的实例
buttton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.exit(0);
}});//现场定义了一个类,并且创建了它的实例。
}
}
//序列化到文件
FileOutputStream fileStream = new FileOutputStream("my.ser");
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(one);
os.close();
//解序列化
FileInputStream fileStream = new FileInputStream("my.ser");
ObjectInputStream os = new ObjectInputStream(fileStream);
Object one = os.readObject();
Game two = (Game)one;
os.close();
public class DailyAdvice{
public void go() {
try {
Socket sock = new Socket("127.0.0.1", 5555);//建立连接
InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());//用StreamReader读取服务器传过来的内容。
BufferedReader reader = new BufferedReader(streamReader);
String advice = reader.readLine();
reader.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public static void main(String [] args) {
DailyAdvice client = new DailyAdvice();
client.go();
}
}
public class MyRunnable implements Runnable{
public void run() {//必须要实现,这是thread运行所需执行的任务
go();
}
public void go() {
doMore();
}
public void doMore() {
System.out.println("something");
}
}
class ThreadTester{
public static void main(String [] args) {
MyRunnable job = new MyRunnable();
Thread th = new Thread(job);
th.start();//开启线程
}
}
一旦线程进入可执行状态,就会在可执行和执行中两种状态切换。
public void go(){
synchronized(this){//需要同步化的代码
//critical stuff
}
}
//服务端程序
public class ChatServer {
ArrayList clientOutputStream;
public class ClientHander implements Runnable{
BufferedReader reader;
Socket sock;
public ClientHander(Socket clientSocket) {
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public void run() {//thread会运行的程序
String message;
try {
while((message = reader.readLine()) != null) {
System.out.println("read "+ message);
tellEveryone(message);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
public void go() {
clientOutputStream = new ArrayList();
try {
ServerSocket server = new ServerSocket(5006);
while(true) {
Socket clientSock = server.accept();
PrintWriter writer = new PrintWriter(clientSock.getOutputStream());
clientOutputStream.add(writer);
Thread t= new Thread(new ClientHander(clientSock));
t.start();//会产生新的线程
System.out.println("got a connection");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//end go
public void tellEveryone(String message) {
Iterator it = clientOutputStream.iterator();
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter)it.next();
writer.println(message);
writer.flush();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
//main
public static void main(String[] args) {
new ChatServer().go();
}
}
1 . 集合中的关系如下图:
2. 当使用compareTo()函数的时候,list中只可以有一个将自己与同类型比较的方法。所以可以使用comparator这个独立的类,自制比较函数。如下:
泛型
下面两个方法的声明
public void eat(ArrayList list){}
public void eat(ArrayList list){}
前者可以使用任何的animal,如可以使用ArrayList作为参数传递,但是后者只有ArrayList才是合法的。与第一句相同功能的声明如下:
public void eat(ArrayList
其实这部分看到后面就没力气了,所以先放一放,等我看完再来更新好啦!(谁可以告诉我:怎么才能充满power~)