摘选自Head First Java和中国大学MOOC上翁恺老师的 PPT 笔记&CSDN上大佬们的回答
plus自己的一些心得体会
内容为Java基础知识(无线程,网络编程知识)
以下是正文:
---------------------------------------------------------------------------------------------------------------------------------
Java Points
0.标识符:
第一个字符:大小写字母 下划线_ $
第二个以后:以上所有 0-9
headfirstjava:
1.P12:条件判断中while(a);a为Boolean integer与Boolean不相容
2.P13:println会在最后面插入换行(normal:print)
3.输出字符串使用+号
4.random()这个方法返回0-1之间的值 注意数值强制类型转换 (int)
5.P21创建类时不一定用public
6.P21注意方法声明 public static void main(String [] args){}
7.P31子类会自动获得父类的功能
8.P32Amoeba这个类可以覆盖shape这个方法
9.对象变量和普通变量的不同,对象变量是对象的管理者而非所有者
10.类定义了对象长什么样,对象则是按照类的定义所制造出来的实体,一个类可以创建很多对象,每个对象有自己的数据。
11.this的作用:http://blog.csdn.net/fzfengzhi/article/details/2174406
一.在方法中与形式参数区别开 成员变量(函数参数):this.i 形式参数:i
二.在一个构造方法中引用另外一个同名构造方法:只有构造方法能调用他,必须注意:就算是构造方法调用构造器,也必须为于其第一行,构造方法也只能调用一个且仅一次构造器 this();
三.返回当前对象:
public ThisTest increment(){
this.i++;
return this;//返回的是当前的对象,该对象属于(ThisTest)
}
12.构造方法:是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。
1)构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。
2)构造方法的调用是在创建一个对象时使用new操作进行的。构造方法的作用是初始化对象。
3)不能被static、final、synchronized、abstract和native修饰。构造方法不能被子类继承。
构造方法(函数)就是为了给类中成员赋初值:自动调用构造函数(一般为赋初值)>进入构造函数后的第一件事是到class中进行定义初始化(length、width)
**重载:一个类中有两个同名的构造方法(函数),可根据形式参数个数(参数表不同)区别开来
class RectConstructor{
int t;
double length;
double width;
double area(){
return length*width;
}
RectConstructor(){//带参数的构造方法(可有可无参数)
t = 0;
}
RectConstructor(double width,double length){//同名函数:**重载
this(); //调用上面的构造方法(t=0) //只能在同名函数中第一句,一个构造方法 只能使用一次
this.length=length;
this.width=width;
}
}
public class RectDemo{
public static void main(String args[]) {
RectConstructor rect1=new RectConstructor(10,20);
RectConstructor rect2=new RectConstructor(3,6);
double ar;
ar=rect1.area();
System.out.println("第一个长方形的面积是"+ar);
ar=rect2.area();
System.out.println("第二个长方形的面积是"+ar);
}
}
13. 成员函数:
定义:类的成员函数的原型要写在类体中,原型说明了函数的参数表和返回值类型。而函数的定义一般在类外面,也可以直接在类内部定义。前者与普通函数不同的是,实现成员函数时要指明类的名称,具体形式为:
返回值类型 类名::函数成员名(参数表){函数体};(类.)
而后者一般为一些短小的函数(5行以内),也就是内联函数。
各类函数中:构造函数、析构函数、拷贝初始化构造函数等是类的成员函数。
class A
{
public:
void B();
private:
int C();
protected:
bool D(int i);
};
那么,B(),C(),D(int)都是A的成员函数
14. Java中的交换函数:用JAVA写一个函数交换两个数字
(C/C++中可以使用指针Java不行)
1. package com.wq.swap;
2.
3. public class SwapNumbers {
4. public int a;
5. public int b;
6.
7. //包装类交换
8. public static void swap (Integer a, Integer b) {
9. Integer temp = a;
10. a = b;
11. b = temp;
12. };
13.
14. //直接交换
15. public static void swap (int a, int b) {
16. int temp = a;
17. a = b;
18. b = temp;
19. };
20.
21. //数组
22. public static void swap (int[] arr) {
23. int temp = arr[0];
24. arr[0] = arr[1];
25. arr[1] = temp;
26. };
27.
28. //成员对象
29. public void swapNum(int a, int b) {
30. this.a = b;
31. this.b = a;
32. };
33.
34. //包装类打印
35. public static void print(Integer m, Integer n) {
36. System.out.println("m=" + m.intValue() + " n=" + n.intValue());
37. }
38. //直接打印
39. public static void print(int a, int b) {
40. System.out.println("a=" + a + " b=" + b);
41. }
42. //对象打印
43. public void print() {
44. System.out.println("a=" + this.a + " b=" + this.b);
45. }
46. //数组打印
47. public static void print(int[] a) {
48. for (int i : a) {
49. System.out.print(i + " ");
50. }
51. System.out.println();
52. }
53.
54.
55. public static void main(String[] args) {
56.
57. System.out.println("------直接交换----------");
58. int a = 2, b = 3;
59.
60. print(a,b);
61. swap(a, b);
62. print(a,b);
63.
64. System.out.println("------包装类交换----------");
65. Integer m = new Integer(2);
66. Integer n = new Integer(3);
67.
68. print(m,n);
69. swap(m, n);
70. print(m,n);
71.
72. System.out.println("-------数组交换---------");
73. int[] arr = {2,3};
74. print(arr);
75. swap(arr);
76. print(arr);
77.
78. System.out.println("-------成员变量交换---------");
79. print(a,b);
80. SwapNumbers sn = new SwapNumbers();
81. sn.swapNum(a, b);
82. sn.print();
83.
84. }
85. }
1. ------直接交换----------
2. a=2 b=3
3. a=2 b=3
4. ------包装类交换----------
5. m=2 n=3
6. m=2 n=3
7. -------数组交换---------
8. 2 3
9. 3 2
10. -------成员变量交换---------
11. a=2 b=3
12. a=3 b=2
15. 面向对象的思维:
程序有什么东西组成(clock:小时分钟秒)>>哪些可以划归为一类
对象中有对象,相似对象组成类
16.Java中private、protected、public和default的区别
public:
具有最大的访问权限,可以访问任何一个在classpath下的类、接口、异常等。它往往用于对外的情况,也就是对象或类对外的一种接口的形式。
protected:
主要的作用就是用来保护子类的。它的含义在于子类可以用它修饰的成员,其他的不可以,它相当于传递给子类的一种继承的东西
default:
有时候也称为friendly,它是针对本包访问而设计的,任何处于本包下的类、接口、异常等,都可以相互访问,即使是父类没有用protected修饰的成员也可以。
private:
访问权限仅限于类的内部,是一种封装的体现,例如,大多数成员变量都是修饰符为private的,它们不希望被其他任何外部的类访问。
注意:java的访问控制是停留在编译层的,也就是它不会在.class文件中留下任何的痕迹,只在编译的时候进行访问控制的检查。其实,通过反射的手段,是可以访问任何包下任何类中的成员,例如,访问类的私有成员也是可能的。
区别:
public:可以被所有其他类所访问
private:只能被自己访问和修改
protected:自身、子类及同一个包中类可以访问
default:同一包中的类可以访问,声明时没有加修饰符,认为是friendly。
17.封装,就是把数据和对这些数据的操作放在一起(对成员变量设访问属性:private...),并且用这些操作把数据掩盖起来,是面向对象的基本概念之一,也是最核心的概念。
我们有一个非常直截了当的手段来保证在类的设计的时候做到封装:
1)所有的成员变量必须是private的,这样就避免别人任意使用你的内部数据;
2)所有public的函数,只是用来实现这个类的对象或类自己要提供的服务的,而不是用来直接访问数据的。除非对数据的访问就是这个类及对象的服务。简单地说,给每个成员变量提供一对用于读写的get/set函数也是不合适的设计。
18.private:
只有这个类内部可以访问
类内部指类的成员函数和定义初始化(用于成员函数,成员变量)
这个限制是对类的而不是对对象的(Fraction例子 对象之间可以相互访问private)
19. public:
不同类之间可以使用(使用==调用、访问、定义变量)
Friendly:(不带private、public的)同一个包内可以互相访问
Public class:任何人可以用这个类定义变量(public class必须定义在它自己的文件中类名与文件名相同)
编译单元:1.一个源代码文件.java 2.一次编译一个 3.一个里面可以有很多类 4.只有一个类可以使public
20. 包:(嵌套包:“.”划分层次)当你的程序越来越大的时候,你就会需要有一个机制帮助你管理一个工程中众多的类了。包就是Java的类库管理机制,它借助文件系统的目录来管理类库,一个包就是一个目录,一个包内的所有的类必须放在一个目录下,那个目录的名字必须是包的名字。
Import:(格式import 包名.类名)在包内引用其他包时需加上(位置位于package行下面///若想import其他包内所有类:import 包名.*)<-->也可以不加,但是在创建其他包的类时要加上包名>>包名.类名
21. static:
类变量:变量都是在对象里面?类里面的“成员变量”!加static变成类变量!对象中是没有的!只是可以访问static的类变量
只可能在装载(进入类时 与创建对象时机无关)时被初始化
类函数:(使用对象中函数必须为:对象名.函数名)直接使用类函数名
22. 容器:
泛型类
储存了一份add入的字符串的副本:
//String a = "str";
//nb.add(a);
//System.out.println(nb.getNote(0));
//a += "11";
//System.out.println(nb.getNote(0));
//nb.add(a, 0);
//System.out.println(nb.getNote(0));
OUTPUT:
str
str
str11
输出(查看内容)可以通过:
System.out.println(a);
OUTPUT:
[first, second, first]
23. For-Each循环:
循环输出字符串数组
等同于
for (int i = 0; i < a.length; i++) {
String s = a[i];
System.out.print(s);
}
是J2SE 1.5提供的另一种形式的for循环,可以用来处理不知道str长度的情况
**对于对象数组而言:
如:for (Valuev :a) {
System.out.println(v.get());
v.set(0);
//v变为管理者
}
创建的v变为管理者,可以修改(a指向的)对象的值
24. Set容器
HashSet:相当于集合:无顺序、元素不重复(重复加入的元素只有一份)
import java.util.HashSet;
HashSet<String> s =new HashSet<String>();
输出(查看内容)可以通过:System.out.println(s);
HashSet<String> s =new HashSet<String>();
s.add("first");
s.add("second");
s.add("first");
System.out.println(s);
OUTPUT:
[first, second]
25. toString函数
目的:想用System.out.println(s);直接输出对象
格式:public String toString() {return ""+i;}//将i变为字符串
Example:
class Value{
private int i;
public void set(int i) {
this.i =i;
}
public int get() {
return i;
}
public String toString() {return ""+i;}
}
------------------------------------------------
public static void main(String[]args) {
Value v =new Value();
v.set(10);
System.out.println(v);
}
-----------------------------------------------
OUTPUT:
10
26. HashMap哈希表
HashMap<key,name>
import java.util.HashMap;
private HashMap<Integer,String>coinnames =new HashMap<Integer,String>();
//不能为int>>>Integer
public Coin() {
coinnames.put(1,"penny");
coinnames.put(10,"dime");
coinnames.put(25,"quarter");
coinnames.put(50,"half-dollar");
coinnames.put(50,"五毛");
//最后一条将第四条覆盖
System.out.println(coinnames.keySet().size());
System.out.println(coinnames);
for(Integerk :coinnames.keySet()) {
String s =coinnames.get(k);
System.out.println(s);
}//遍历哈希表
}
OUTPUT:
4
{1=penny, 50=五毛, 25=quarter, 10=dime}
penny
五毛
quarter
dime
学生成绩的数据结构
如果要写程序表达一个班级的很多个学生的很多门课的成绩,应该如何表达这些数据?
如果我们希望通过学生的姓名,可以找到他的所有的成绩,而每一门课的成绩,是由课程名称和分数构成的。
而如果我们还希望这个程序能找出某一门课的全部学生的成绩应该怎样做呢?
注意,并非所有的学生都参加了所有的课程。
package hello;
import java.util.HashMap;
public class Scores {
/* [
* "学生名字":
* [
* "课程名称": 成绩
* ]
* ]
*/
HashMap<String, HashMap<String, Integer>> scores =new HashMap<String, HashMap<String, Integer>>();
/*
* 创建或重置学生
*/
public HashMap<String, Integer> set_student(String student_name) {
HashMap<String, Integer> student = new HashMap<String, Integer>();
scores.put(student_name, student);
return student;
}
/*
* 添加或重置学生课程成绩
*/
public void set_score(String student_name, String class_name, Integer score) {
HashMap<String, Integer> student = scores.get(student_name);
if (student ==null) {
student = set_student(student_name);
}
student.put(class_name, score);
}
/*
* 通过名称获取该学生的所有课程跟成绩
*/
public HashMap<String, Integer> get_student(String student_name) {
return scores.get(student_name);
}
/*
* 通过课程名称获取所有学生以及成绩
*/
public HashMap<String, Integer> get_class(String class_name) {
HashMap<String, Integer> student_score =new HashMap<String, Integer>();
for ( String student_name : scores.keySet() ) {
HashMap<String, Integer> student = scores.get(student_name);
Integer score = student.get(class_name);
if (score !=null) {
student_score.put(student_name, score);
}
}
return student_score;
}
public static void main(String[] args) {
Scores value = new Scores();
for (int i = 0; i < 10; i++) {
value.set_student("student_" + i);
for (int j = 0; j < 5; j++) {
value.set_score("student_" + i,"class_" + j, (int)(Math.random() * 100.0));
}
}
System.out.println("student_2: " + value.get_student("student_2"));
System.out.println("class_3: " + value.get_class("class_3"));
}
}
27. 继承
父类与子类的关系:
对理解继承来说,最重要的事情是,知道哪些东西被继承了,或者说,子类从父类那里得到了什么。答案是:所有的东西,所有的父类的成员,包括变量和方法,都成为了子类的成员,除了构造方法。构造方法是父类所独有的,因为它们的名字就是类的名字,所以父类的构造方法在子类中不存在。除此之外,子类继承得到了父类所有的成员。
但是得到不等于可以随便使用。每个成员有不同的访问属性,子类继承得到了父类所有的成员,但是不同的访问属性使得子类在使用这些成员时有所不同:有些父类的成员直接成为子类的对外的界面,有些则被深深地隐藏起来,即使子类自己也不能直接访问。下表列出了不同访问属性的父类成员在子类中的访问属性:
父类成员访问属性 | 在父类中的含义 | 在子类中的含义 |
public | 对所有人开放 | 对所有人开放 |
protected | 只有包内其它类、自己和子类可以访问 | 只有包内其它类、自己和子类可以访问 |
缺省 | 只有包内其它类可以访问 | 如果子类与父类在同一个包内:只有包内其它类可以访问 否则:相当于private,不能访问 |
private | 只有自己可以访问 | 不能访问 |
public的成员直接成为子类的public的成员,protected的成员也直接成为子类的protected的成员。Java的protected的意思是包内和子类可访问,所以它比缺省的访问属性要宽一些。而对于父类的缺省的未定义访问属性的成员来说,他们是在父类所在的包内可见,如果子类不属于父类的包,那么在子类里面,这些缺省属性的成员和private的成员是一样的:不可见。父类的private的成员在子类里仍然是存在的,只是子类中不能直接访问。我们不可以在子类中重新定义继承得到的成员的访问属性。如果我们试图重新定义一个在父类中已经存在的成员变量,那么我们是在定义一个与父类的成员变量完全无关的变量,在子类中我们可以访问这个定义在子类中的变量,在父类的方法中访问父类的那个。尽管它们同名但是互不影响。
在构造一个子类的对象时,父类的构造方法也是会被调用的,而且父类的构造方法在子类的构造方法之前被调用。在程序运行过程中,子类对象的一部分空间存放的是父类对象。因为子类从父类得到继承,在子类对象初始化过程中可能会使用到父类的成员。所以父类的空间正是要先被初始化的,然后子类的空间才得到初始化。在这个过程中,如果父类的构造方法需要参数,如何传递参数就很重要了。
//Source-->Generate Constructor using field...
//自动生成>>>
//public CD(Stringtitle, Stringartist,int numofTracks,int //playingTime, Stringcomment) {
//super();
//this.title =title;
//this.artist =artist;
//this.numofTracks =numofTracks;
//this.playingTime =playingTime;
//this.comment =comment;
//}
Java的继承只允许单继承,即一个类只能有一个父类。
Extends
可以访问到父类protected的变量
用super(变量名);调用父类构造器来初始化子类变量
如果子类中有名字与父类中某一变量相同的变量,父类的被隐藏
可以通过父类的函数修改父类的被隐藏的变量
调用父类的函数:super.函数名();
28. 多态
1子类对象可以赋值给父类对象
2子类对象可以传递给需要父类对象的函数
3子类对象可以放在存放父类对象的容器里
静态 声明类型
动态 动态类型
造型:
造型:把一个对象赋给一个变量
向上造型:把子类的对象赋给父类的变量
默认 不需要运算符总是安全的
(父类对象不能赋给子类对象)
可以用造型:(实际管理对象不匹配时,会编译错误)
c = (Car) v;
只有当v这个变量实际管理的是Car才行
对比类型转换:
造型:当做另外一种类型看待,并不是转变为另一种对象
类型转换:将数值转换
多态:
绑定:
Java是动态绑定
覆盖:
29. 类型系统:
Object类:
toString:转变为字符串 可以将不是字符串的东西转换为字符串
String s = “a” + cd;
在类中建立toString:Source>>Generate toString
equals:判断两个管理者是否管理同一个对象
Source>>Override/Implement Methods
@Override--->注意:覆盖了父类的函数,要和父类此函数类似:public,object类(可以去掉)
public boolean equals(Objectobj) {
CD cc = (CD)obj;
return artist.equals(cc.artist);
}
通过向下造型,避免obj中无artist情况
30. openDeclaration ---> F3查看函数
31. 封装
用封装来降低耦合度(类和类之间的关系称为耦,耦合度越低越好)
32. StringBuffer
、、StringBuffer sb = new StringBuffer();
、、Sb.append(“需要增加的字符串”);
StringBuffer 为可修改的String对象 可以减少内存使用空间
StringBuffer创建出字符串,用append方法可以在初始字符串后面增加内容
以上内容的复杂形式:
、、String sb = “”;
、、sb += “需要添加的内容”;
33. 可扩展性
以框架+数据来提高可扩展性
用容器增加灵活性
Game中
//可扩展性
lobby.setExit("up",pub);
pub.setExit("down",lobby);
Room中
private HashMap<String,Room>exits =new HashMap<String,Room>();
public void setExit(Stringdir,Roomroom) {
exits.put(dir,room);
}
public String getExitDesc() {
StringBuffersb =new StringBuffer();
for(Stringdir:exits.keySet()) {
sb.append(dir);
sb.append(" ");
}
// if(northExit != null)
// sb.append("north ");
// if(southExit != null)
// sb.append("south ");
// if(eastExit != null)
// sb.append("east ");
// if(westExit != null)
// sb.append("west ");
return sb.toString();
}
public Room getExit(Stringdirection) {
return exits.get(direction);
// Roomret = null;
// if(direction.equals("north")) {
// ret = northExit;
// }
// if(direction.equals("east")) {
// ret = eastExit;
// }
// if(direction.equals("south")) {
// ret = southExit;
// }
// if(direction.equals("west")) {
// ret = westExit;
// }
// returnret;
}
Handler:
34. 抽象 abstract
我们用abstract关键字来定义抽象类。抽象类的作用仅仅是表达接口,而不是具体的实现细节。抽象类中可以存在抽象方法。抽象方法也是使用abstract关键字来修饰。抽象的方法是不完全的,它只是一个方法签名而完全没有方法体。
如果一个类有了一个抽象的方法,这个类就必须声明为抽象类。如果父类是抽象类,那么子类必须覆盖所有在父类中的抽象方法,否则子类也成为一个抽象类。一个抽象类可以没有任何抽象方法,所有的方法都有方法体,但是整个类是抽象的。设计这样的抽象类主要是为了防止制造它的对象出来。
抽象类中的函数可为普通函数,也可为抽象函数(abstract无{}):子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。);
package shapes;
import java.awt.Graphics;
public abstract class Shape {
public void fun() {
System.out.println("存在方法体的方法");
}
public abstract void draw(Graphicsg);
}
抽象类不能产生对象无法实例化(抽象方法没有方法体,没有方法体就无法进行调用),可以定义变量
(1)抽象类中有构造方法么?
由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。
并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。
范例如下:
package com.wz.abstractdemo;
abstract class A{//定义一个抽象类
public A(){
System.out.println("*****A类构造方法*****");
}
public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
}//单继承
class B extends A{//B类是抽象类的子类,是一个普通类
public B(){
System.out.println("*****B类构造方法*****");
}
@Override
public void print() {//强制要求覆写
System.out.println("Hello World !");
}
}public class TestDemo {
public static void main(String[] args) {
A a =new B();//向上转型
}
}
执行结果:
*****A类构造方法*****
*****B类构造方法*****
(2)抽象类可以用final声明么?
不能,因为抽象类必须有子类,而final定义的类不能有子类;
(3)抽象类能否使用static声明?
先看一个关于外部抽象类的范例:
package com.wz.abstractdemo;
static abstract class A{//定义一个抽象类
public abstract voidprint();
}
class B extends A{
public voidprint(){
System.out.println("**********");
}
}public class TestDemo {
public static void main(String[] args) {
A a =new B();//向上转型
a.print();
}
}
执行结果
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Illegal modifier for the class A; only public, abstract & final are permitted
at com.wz.abstractdemo.A.<init>(TestDemo.java:3)
at com.wz.abstractdemo.B.<init>(TestDemo.java:9)
at com.wz.abstractdemo.TestDemo.main(TestDemo.java:18)
再看一个关于内部抽象类:
package com.wz.abstractdemo;
abstract class A{//定义一个抽象类
static abstract class B{//static定义的内部类属于外部类
public abstract voidprint();
}
}
class C extends A.B{
public voidprint(){
System.out.println("**********");
}
}public class TestDemo {
public static void main(String[] args) {
A.B ab =new C();//向上转型
ab.print();
}
}
执行结果:
**********
由此可见,外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。使用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。
(4)可以直接调用抽象类中用static声明的方法么?
任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。
范例如下:
package com.wz.abstractdemo;
abstract class A{//定义一个抽象类
public static void print(){
System.out.println("Hello World !");
}
}
public class TestDemo {
public static void main(String[] args) {
A.print();
}
}
运行结果:
Hello World !
(5)有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。
范例如下:
package com.wz.abstractdemo;
abstract class A{//定义一个抽象类
public abstract void print();
private static class B extends A{//内部抽象类子类
public void print(){//覆写抽象类的方法
System.out.println("Hello World !");
}
}
//这个方法不受实例化对象的控制
public static AgetInstance(){
return new B();
}
}
public class TestDemo {
public static void main(String[] args) {
//此时取得抽象类对象的时候完全不需要知道B类这个子类的存在
A a = A.getInstance();
a.print();
}
}
运行结果:
Hello World !
35. 接口
Interface--implements
Int guess = Integer.parseInt(stringGuess);