Java 继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
类的继承格式
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的
1 | class 父类 { |
例子:
1 | public class Animal { |
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的
1 | class 父类 { |
例子:
1 | public class Animal { |
我们尝试实现一个投票应用,具体的需求是用户进入应用首先查看到“学科介绍”页面,该页面显示了一个学校所开设的所有学科;通过点击某个学科,可以进入“老师介绍”页面,该页面展示了该学科所有老师的详细情况,可以在该页面上给老师点击“好评”或“差评”,但是会先跳转到“登录页”要求用户登录,登录成功才能投票;对于未注册的用户,可以在“登录页”点击“新用户注册”进入“注册页”完成用户注册,注册成功后会跳转到“登录页”,注册失败会获得相应的提示信息。
从上面对投票应用需求的描述中我们可以分析出三个业务实体:学科、老师和用户。学科和老师之间通常是一对多关联关系(一个学科有多个老师,一个老师通常只属于一个学科),用户因为要给老师投票,所以跟老师之间是多对多关联关系(一个用户可以给多个老师投票,一个老师也可以收到多个用户的投票)。首先修改应用下的models.py文件来定义数据模型,先给出学科和老师的模型。
NoSQL是一项全新的数据库革命性运动,虽然它的历史可以追溯到1998年,但是NoSQL真正深入人心并得到广泛的应用是在进入大数据时候以后,业界普遍认为NoSQL是更适合大数据存储的技术方案,这才使得NoSQL的发展达到了前所未有的高度。2012年《纽约时报》的一篇专栏中写到,大数据时代已经降临,在商业、经济及其他领域中,决策将不再基于经验和直觉而是基于数据和分析而作出。事实上,在天文学、气象学、基因组学、生物学、社会学、互联网搜索引擎、金融、医疗、社交网络、电子商务等诸多领域,由于数据过于密集和庞大,在数据的分析和处理上也遇到了前所未有的限制和阻碍,这一切都使得对大数据处理技术的研究被提升到了新的高度,也使得各种NoSQL的技术方案进入到了公众的视野。
1 | 非关系型数据库的优势: |
NoSQL数据库按照其存储类型可以大致分为以下几类:
用到的HashTable:
HashTable.cpp:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196#ifndef _HASH_MAP
#define _HASH_MAP
#include <vector>
#include <string>
using namespace std;
int operator % (const string & text, int max) {
int code = 0;
for (int i = 0; i < text.size(); ++ i) {
int code1 = text[i];
code1 = code1 << (i * 8 % 24);
code = code ^ code1;
}
return code % max;
}
class NoSuchKeyException {};
template <typename K, typename V>
class HashTable
{
private:
class Entry
{
public:
K key;
V value;
bool isInUse;
Entry() {
isInUse = false;
}
};
Entry * entries;
int capacity;
int count;
void initialize(int capacity2) {
count = 0;
capacity = capacity2;
entries = new Entry[capacity];
}
void assign(const HashTable & map2) {
count = map2.count;
capacity = map2.capacity;
entries = new Entry[capacity];
for (int i = 0; i < capacity; ++ i) {
entries[i] = map2.entries[i];
}
}
public:
HashTable() {
initialize(2);
}
~HashTable() {
delete [] entries;
}
HashTable(const HashTable & map2) {
assign(map2);
}
HashTable & operator = (const HashTable & map2) {
delete [] entries;
assign(map2);
return (*this);
}
void clear() {
delete [] entries;
initialize(2);
}
private:
int hashIndex(const K & key) const {
return key % capacity;
}
int find(const K & key) const {
int index = hashIndex(key);
while (true) {
if (! entries[index].isInUse) {
return index;
}
if (entries[index].key == key) {
return index;
}
index = (index + 1) % capacity;
}
}
void resize(int capacity2) {
Entry * entries0 = entries;
int capacity0 = capacity;
initialize(capacity2);
for (int i = 0; i < capacity0; ++ i) {
if (entries0[i].isInUse) {
put(entries0[i].key, entries0[i].value);
}
}
delete [] entries0;
}
public:
void put(const K & key, const V & value) {
int index = find(key);
entries[index].value = value;
if (entries[index].isInUse) return;
entries[index].isInUse = true;
entries[index].key = key;
++ count;
if (count > capacity / 2) {
resize(capacity * 2);
}
}
V get(const K & key) const {
int index = find(key);
if (! entries[index].isInUse) {
throw NoSuchKeyException();
}
return entries[index].value;
}
bool remove(const K & key) {
int index = find(key);
if (! entries[index].isInUse) return false;
fillNotInUseEntry(index);
-- count;
if (count < capacity / 4) {
resize(capacity / 2);
}
return true;
}
private:
void fillNotInUseEntry(int index) {
int next = index;
while (true) {
next = (next + 1) % capacity;
if (! entries[next].isInUse) {
entries[index].isInUse = false;
return;
}
int index0 = hashIndex(entries[next].key);
if (index < next) {
if (index0 > index &&
index0 <= next) continue;
}
else {
if (index0 > index ||
index0 <= next) continue;
}
entries[index] = entries[next];
index = next;
}
}
public:
bool containsKey(const K & key) const {
int index = find(key);
return (entries[index].isInUse);
}
int size() const {
return count;
}
vector<K> getKeys() const {
vector<K> vec;
for (int i = 0; i < capacity; ++ i) {
if (entries[i].isInUse) {
vec.push_back(entries[i].key);
}
}
return vec;
}
};
#endif
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error;如果你用System.out.println(11/0),那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常。
异常发生的原因有很多,通常包含以下几大类:
网络通信时连接中断,或者JVM内存溢出。
这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。-
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。
下面是创建 Scanner 对象的基本语法:
Scanner s = new Scanner(System.in);
接下来我们演示一个最简单的数据输入,并通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据:
使用 next 方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 从键盘接收数据
// next方式接收字符串
System.out.println("next方式接收:");
// 判断是否还有输入
if (scan.hasNext()) {
String str1 = scan.next();
System.out.println("输入的数据为:" + str1);
}
scan.close();
}
}
1 | $ javac ScannerDemo.java |
com 字符串并未输出
使用 nextLine 方法:
1 | import java.util.Scanner; |
1 | $ javac ScannerDemo.java |
可以看到 com 字符串输出。
next():
next() 不能得到带有空格的字符串。
nextLine():
以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
1 | import java.util.Scanner; |
1 | $ javac ScannerDemo.java |