上午小組總結:
關于收獲:
面試時考查:
- Java基礎
- 邏輯思維
- 讀代碼能力
- 寫代碼能力(編程題)
- 算法題
學習過程中 要從網上找題刷題!
看公司的需求 去實習看需求 再去學習更多的知識
對于Person類:
public class Person{
// 定義了兩個成員變量
public String name;
public int age;
// 定義了一個say方法
public void say(String content){
System.out.println(content);
}
}
類是一種引用數據類型,因此程序中定義的Person類型的變量實際上是一個引用,它被存放在棧內存中,指向實際的Person對象;而真正的Person對象則存放在堆(heap)內存中
// 定義p變量的同時并為p變量賦值
Person p = new Person();
// 訪問p的name實例變量,直接為該變量賦值
p.name = "暗影";
// 調用p的say()方法,聲明say()方法時定義了一個形參
// 調用該方法必須為形參指定一個值
p.say("Java 從入門到放棄");
// 直接輸出p的name實例變量,將輸出暗影
System.out.println(p.name);
對應:
數組在內存中的運行機制:
我們知道數組變量屬于引用數據類型
比較重點說明:
先來看代碼:(嘗試自己理解下)
若有不清楚請看下面的解釋:
先來了解下數組在內存中的運行機制:
我們知道數組變量屬于引用數據類型
數組元素和數組變量在內存里是分開存放的!
數組只是一個引用類型的變量,因此使用它定義一個變量時,僅表示定義了一個引用變量(也就是定義了一個指針) 這個引用變量可以指向任何有效的內存。
只有當該引用指向有效內存后,才可以通過該數組變量來訪問數組元素。
引用變量是訪問內存中真實對象的根本方式,
也就是說,與所有引用變量相同,如果希望在程序中訪問數組對象本身,則只能通過這個數組的引用變量來訪問它。
實際的數組對象被存放在堆(heap)內存中,而引用該數組對象的 數組引用變量(要是一個局部變量)被存儲在棧(stack)內存中。
即棧內存中的引用變量指向堆內存中的對象!
再來看一下創建數組對象區別:
int[] a = {1,2,3};
int[] b = new int[] {1,2,3};
int[] c = a;
int[] d = a.clone();
首先注意:
int[] a = {1,2,3};
和
int[] b = new int[] {1,2,3};
都是數組的靜態初始化方式,int[] a = {1,2,3}; 是 int[] b = new int[] {1,2,3}; 的簡化形式。
(另外注意 只有在定義數組的同時執行數組初始化才支持使用簡化的靜態初始化形式)
int[] a = {1,2,3};
int[] b = new int[] {1,2,3};
后內存中引用指向:
(注意a,b指向不同的堆內存對象)
int[] c = a;
完成的動作是: 在棧中創建c引用變量 c指向 (a指向的對象):
再來看這個
int[] d = a.clone();
先看java doc 文檔的說明:
即clone()解釋為:返回一個實例(instance)的克隆,即:
創建數組對象說明完成,再來看比較的區別:
首先要知道:原始基本數據類型的變量之間的==與!=所做的是相等性比較——值是否相等,而引用數據類型變量之間的==與!=做的是同一性比較——是否指向同一對象。
所以數組作為引用數據類型 == 判斷的是同一性比較(是否指向同一對象)
數組自身的equals() 函數 和 == 一樣,也比較 兩者是否指向同一對象:
且又因為:
所以前兩種比較結果一致:
再來看最后一種比較方式:(Arrays.equals(a,b),即Java8 提供的增強工具類Arrays)
可見Arrays.equals(a,b)比較的是內容相等,若內容一樣則返回true
老師還讓練習了自己寫equals() 函數,要求比較數組內容,并且不考慮數組元素順序(即認為{1,2,3}和{2,1,3}相等)
下面是我的代碼和測試:
public class Test2 {
public static boolean equals(int[] a, int[] b) {
if(a.length != b.length) {
return false;
}else{
BubbleSort(a);
BubbleSort(b);
for(int i=0; i<a.length;++i){
if(a[i] != b[i]) return false;
}
}
return true;
}
public static void BubbleSort(int[] a) {
int temp;
for(int i=0;i<a.length-1;++i) {
for(int j=0;j<a.length - i - 1;++j) {
if(a[j] > a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
public static void main(String[] args) {
int[] a = {1,2,3};
int[] t = {2,1,3};
System.out.println("自己寫的equals函數測試: " + equals(a, t));
}
}
控制臺結果:
自己寫的equals函數測試: true
練習了冒泡排序算法:
public class BubbleSort {
public static void main(String[] args) {
int[] a = {3,2,6,7,8,1,22,55,66};
int temp;
for(int i=0;i<a.length-1;++i) {
for(int j=0;j<a.length - i - 1;++j) {
if(a[j] > a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
for(int i:a) {
System.out.println(i);
}
}
}
關于更多算法與數據結構請關注我的文集:
C/C++ java 算法與數據結構
(后續我會更新常用算法及數據結構的思想及其C++和Java源碼實現)
關于拓展:
自己已經過了一遍Linux:
Ubuntu-server-64:
學習了一些常用命令
(很多記不住 需要下來多用多記憶)
但是設置靜態IP出現問題,正在查找解決方法:
桌面設置靜態失敗:
Hadoop:
0 分布式
由分布在不同主機上的進程協同在一起,才能構成整個應用。
(同一臺主機上的不用進程,他們之間的交互也屬于分布式)
1 海量數據
- 1 byte = 8bit
- 1024 B = 1 M
- 1024 M = 1 G
- 1024 G = 1 T
- 1024 T = 1 P
- 1024 P = 1 E
- 1024 E = 1 Z
- 1024 Z = 1 Y
- 1024 Y = 1 N
2 存儲(大數據需要解決的問題1)
- 分布式存儲
3 計算 (大數據需要解決的問題2)
- 分布式計算
4 hadoop (大象)
- 創始人Doug Cutting
- Apache 開源軟件
- 計算框架(分布式、可靠、可伸縮)
reliable, scalable, distributed
可伸縮指的是 擴容 (隨時增加或減少節點) - 搜索引擎、海量數據存儲
趙老師總結:
- 以后總結要展示一些代碼(可以現場敲代碼)
- 要提出問題 嘗試解決
下午學習:
包裝類的享元模式:
顧名思義:共享元對象。如果在一個系統中存在多個相同的對象,那么只需要共享一份對象的拷貝,而不必為每一次使用創建新的對象。
享元模式是為數不多的、只為提升系統性能而生的設計模式。它的主要作用就是復用對象,以節省內存空間和對象創建時間。
(num 和 num1共享內存,1和2不共享內存)
總結常用包裝類中的常用方法:
String類的常用方法:
ASCII碼大小寫字母相差32 !!!
** replace : **
replace 可去除一個字符串中所有的空格
(中文和半角的中文不一樣)
Debug技巧:
- 打印
- logger (可控制打印的級別)
- debug調試(設置斷點)
復習:
final關鍵字:
- 修飾類,不能被繼承
- 修飾方法,不能覆蓋
- 修飾變量,為常量
方法覆蓋操作:
- 靜態覆蓋靜態,非靜態覆蓋非靜態,靜態性約束性保持一致
- 覆蓋方法時,權限可以放大,但不可以縮小
類的成員:
- 成員變量
- 成員函數
- 構造代碼塊
- 靜態代碼塊
- 另一個類
內部類:
- 定義在類內部的類稱為內部類
- 內部類可以在類的成員位置上(方法外)
- 內部類也可以在方法內定義
- 從內部類引用的本地變量必須是最終變量或實際上的最終變量(雖然Java8已經不要求內部類訪問的局部變量聲明時必須加final修飾,但是內部類內部中絕不能改變局部變量的值)
內部類示例1: (函數外)
public class Test {
public static void main(String[] args) {
Benz benz = new Benz();
benz.run();
}
}
class Benz {
String color;
int tires;
public void run() {
Engine e = new Engine();
e.fire("Key0001");
System.out.println("run...");
}
class Engine {
public void fire(String key) {
System.out.println("key ready : " + key);
System.out.println("fires...");
}
}
}
輸出:
key ready : Key0001
fires...
run...
內部類示例2: (函數內)
public class Test {
public static void main(String[] args) {
Benz benz = new Benz();
benz.run("key888..");
}
}
class Benz {
String color;
int tires;
public void run(String key) {
class Engine {
public void fire() {
System.out.println("key ready : " + key);
System.out.println("fires...");
}
}
Engine e = new Engine();
e.fire();
System.out.println("run...");
}
}
內部類引用的本地變量必須是最終變量:
class Benz {
String color;
int tires;
public void run(String key) {
int k1 = 11111;
int k2 = 22222;
class Engine {
k1 = 33333;
public void fire() {
k2 = 44444;
System.out.println("key ready : " + key);
System.out.println("fires...");
}
}
Engine e = new Engine();
e.fire();
System.out.println("run...");
}
}
k1 k2都錯誤: (把k1注釋掉 k2也報錯)
(可以把內部類理解為黑箱,若黑箱在里面改變局部變量的值,則內部類外邊的可能會受影響)
抽象類:
-
抽象定義
- 抽象就是從多個實物中講共性,本質的內容抽取出來(例如,狼和狗共性都是犬科,犬科就是抽象出來的概念)
-
抽象類
Java中可以定義沒有方法體的方法,該方法的具體實現由子類完成,該方法稱為抽象方法,包含抽象方法的類就是抽象類。
若函數沒有方法體,那么它必須是抽象的(即加abstract關鍵字),并且抽象方法必須在抽象類中。
抽象類中可以沒有抽象方法
抽象類不能實例化
抽象類通過其子類實例化,而子類需要覆蓋掉抽象類中所有的抽象方法后才可以創建對象,否則該子類也是抽象類。
//抽象類
abstract class Animal {
// 抽象方法
abstract public void cry();
}
抽象類不能實例化:
抽象類通過其子類實例化:
public class Test{
public static void main(String[] args){
// 不能實例化 Animal
// Animal a = new Animal();
Dog d = new Dog();
d.cry();
}
}
//抽象類
abstract class Animal{
// 抽象方法
abstract public void cry();
}
class Dog extends Animal{
// 實現抽象方法
public void cry(){
System.out.println("汪汪...");
}
}
- 抽象類繼續
- 抽象類雖不能直接實例化,但是有構造函數!
思考:抽象關鍵字abstract不可以和哪些關鍵字共存?
回答問題前先總結以下關鍵字:
-
private (先不考慮修飾類)
- 不能被繼承
- 不能被訪問
-
final
- 修飾類 不能被繼承
- 修飾方法 不能被覆蓋
- 修飾成員變量 不能被改變(為常量)
-
abstract(可以修飾方法 和 類)
- 抽象類不能實例化,只能被繼承
- 抽象方法 子類必須實現
-
static
- 和對象無關,只和類有關
非法修飾組合:
- private + abstract
- final + abstract