基礎知識的總結
數據類型:基本數據類型和引用數據類型
基本數據數據類型(boolean.byte.short.int.lang.float.double.char)
引用類型(類、接口、數組)
重載(overLoad)和重寫(override)
重載滿足要素:方法名相同、參數的類型和參數的個數不同,和方法返回值、修飾符等無關
重寫滿足要素:方法名相同、形參列表相同、返回值類型比父類返回值更小或相等、訪問權限比父類方法更大或相等
java的標示符規則:
1.字母、數字、下劃線、美元符號,並且不能以數字開頭
2.標示符不能爲java的關鍵字和保留字符(goto)
基本類型轉換字符串的方法:
基本類型轉換成字符串的的方法:
第一種:String.valueof(基本類型)
第二種:空字符串加上基本類型,得到基本類型字符串(這裏是空字符串不是空格字符串)
第三種:調用對象的toString()
字符串轉換成基本類型的兩個方法:
1、調用基本類型封裝類的paresexxx靜態方法
2、用字符串構造基本類型,再調用封裝對象的xxxValue方法
------------------------------------
Set set = hashMap.keySet();
//問題1:hashMap.keySet方法返回一個Set對象,Set是接口,
//接口可以有引用,並指向其子類對象。但是怎麼可以有一個引用set指向自己的對象呢?
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
public class CollectionDemo {
public static void main(String[] args) {
Person p1 = new Person(21);
Person p2 = new Person(23);
Person p3 = new Person(21);
HashMap hashMap = new HashMap();
hashMap.put("zhangsan", p1);
hashMap.put("lisi", p2);
hashMap.put("wangwu", p3);
Set set = hashMap.keySet();
//問題1:hashMap.keySet方法返回一個Set對象,Set是接口,
//接口可以有引用,並指向其子類對象。但是怎麼可以有一個引用set指向自己的對象呢?
Iterator i = set.iterator();
while(i.hasNext()){
String s = i.next();//這裏提示錯誤,應該把s的類型改爲person
//問題2:i.next方法應該返回一個String,這裏爲什麼會報錯?
解答:其實在java的hashMap中還有一個內部類,這個類就是keySet
你可以在你的代碼中用 System.out.println(hashMap.keySet().getClass().getName())試試看,
返回的java.util.HashMap$KeySet,這就代表Set通過keySet方法獲得的Set對象其實是hashMap的內部類實例。而對於註釋部分的keySet,因爲keySet其實只需要有一個就可以了,因爲每個hashMap集合只可能有一種key隊列,多了就浪費空間了,所以除了第一次會new一個新的對象,你再次調用,就把以前已經創建的keyset對象給你
//並提示應該把s的類型改爲person?
System.out.println(i.next());//而這裏直接打印出的又是person。
解釋:②因爲你沒有加泛型限定,所以i.next返回的是Object類型的,必須要進行強轉或者對迭代器進行類型限定,你這裏就限定成String類型
}
}
}
Constructor[] constructors=Class.forName("java.lang.String").getConstructors();
---------------------------------------------------------------------------------
synchronized:在代碼裏,synchronized類似“面向對象”,修飾類、方法、對象
Lock:不作爲修飾,類似“面向過程”,在方法中需要鎖的時候lock,在結束的時候,unlock(一般在finally塊裏)
代碼:
public void metho(){
synchronized(this){//舊鎖,無須人工釋放
System.out.println(1);
}
}
public void method2(){
Lock lock=new ReentrantLock();
lock.lock();//上鎖
try{
System.out.println(2);
}finally{
lock.unlock();//解鎖
}
synchronzied--對象加鎖:
所有對象都自動含有單一的鎖,jvm負責跟蹤對象被加鎖的次數。如果一個對象被鎖,其記數變爲0。在任務(線程)第一次給對象加鎖的時候,記數變爲1。每當這個相同的任務(線程)在此對象上獲得鎖時,記數會遞增。只有首先獲得鎖的任務(線程)才能繼續獲取該對象上的多個鎖。每當任務離開時,記數遞減,當記數爲0的時候,鎖被完全釋放。sychronized就是基於這個原理,同時synchronized考某個獨享的單一鎖技術的次數來判斷是是否被鎖,所以無需(也不能)人工干預鎖的獲取和釋放。
}
Lock---基於棧中的框架,而不是對象級別:
lock不同於synchronized,它基於棧中的框架而不是某個具體對象,所以Lock只需在棧裏設置鎖的開始和結束(lock和unlock)的地方,就行了(人工必須註明),不需要關心框架大小對象的變化等等。這麼做的好處是Lock能提供無條件的、可輪詢的、定時、可中斷的鎖獲取操作,相對於synchronized來說,synchronized的鎖的獲取和釋放不在一個模塊裏,獲取和釋放的順序必須相反,而Lock則可以在不同範圍內獲取釋放,並且順序無關。
------------------------------------------------------------------
TreeSet的排序方式有下面兩種:
1:讓元素自身具備比較性。元素需要實現Comparable接口,覆蓋compareTo方法。
也種方式也成爲元素的自然順序,或者叫做默認順序。
class Student implements Comparable//該接口強制讓學生類具備比較性
{ Student()
{}
public int compareTo(Object obj)
{}
}
2:當元素自身不具備比較性時,或者具備的比較性不是所需要的。這時就需要讓集合自身具備比較性。
在集合初始化時,就有了比較方式。
這時就需要定義一個比較器類去實現Comparator,並重寫compare方法。
class MyCompare implements Comparator //自定義比較器,使集合具備比較性
{ public int compare(Object o1,Object o2)
{}
}
在定義集合時,需要根據實際情況選擇排序方式:
1、TreeSet ts =new TreeSet(); //此時的排序方式爲第一種,即元素的自然排序方式。
2、TreeSet ts =new TreeSet(new MyCompare()); //此時的排序方式爲第二種,即集合自身具備比較性。
---------------------------------------------------------------------------------------------
Set:無序,不可以重複元素
|---Hashset:數據結構式哈希表。線程是非同步的。
包成元素唯一性的原理:判斷元素的hashCode值是否相同
如果相同,還會繼續判斷元素的equals方法,是否爲true。
採用hash表
|---Treeset:可以對Set集合中的元素進行排序
底層數據結構式二叉樹
保證元素唯一性的依據:
compareTo方法 return ();和hash表沒關係
TreeSet排序的第一種方式:讓元素自身具備比較性。元素需要實現Comparable接口,覆蓋compareTo方法
這種方式也成爲元素的自然排序,或者叫做默認排序。
注意:排序時,當主要條件相同時,一定判斷一下次要條件。當對象很多時,耗時。
treeset採用二叉樹形式保存數據!保存數據後查詢的時候採用折半查詢
TreeSet排序的第二種方式:
當元素自身不具備比較性時,或者具有的比較性不是不是所需要的。
這時就需要讓集合自身具備比較性,定義比較器,將比較器對象作爲參數傳遞給TreeSet集合的構造函數
在集合初始化時,就有了比較方式。
----------------------------------------------------------------------------------------------
解釋是這樣的,當你往集合中添加第一個元素的時候,(不管你重寫不重寫)集合都會自動調用hasCode方法,算出一個哈希值
當你再往集合中添加元素時。系統會再算出此元素的哈希值,並自動判斷跟之前元素的哈希值是否相同。如果相同,就需要equals方法,來判斷元素的屬性是否都一樣。
給你舉個例子
元素要往哈希表結構的容器中存儲,必須具備hashCode和equals方法。(Object已經提供了這兩個方法。 對象創建在堆內存中就是因爲有了hashCode方法.)
//覆寫hashCode方法的原因。Object中的hashCode是本地(windows)方法,只算內存地址.
//不覆寫會根據內存地址判斷資料相同的人不是同一個人。
//滿足不了人的姓名和年齡相同 既爲同一個人的要求。所以要依據對象自身特別不同。
//覆寫equals的原因:HashSet判斷元素唯一的依據是自動調用equals方法。
//不覆寫的話,如果hash值萬一相同的話,就需要逐個比較元素的屬性,而原來的equals滿足不了這個要求
代碼如下:
@Override
// 覆寫hashCode方法的原因。Object中的hashCode是本地(windows)方法,只算內存地址.
// 不覆寫會根據內存地址判斷資料相同的人不是同一個人。
// 滿足不了 人的姓名和年齡相同 既爲同一個人的要求。所以要依據對象自身特別不同。
public int hashCode() {
final int prime = 31;
return name.hashCode() + age * prime;
// *prime的原因。防止姓名的哈希值是40,年齡是20 與姓名的哈希值是20,年齡是40 。而引起哈希值相同,多運行equals方法
}
@Override
// 覆寫equals的原因:HashSet判斷元素唯一的依據是自動調用equals方法。
// 不覆寫的話,如果hash值萬一相同的話,就需要逐個比較元素的屬性,而原來的equals滿足不了這個要求,
//如果主方法中添加的元素內容不是一模一樣的,幾乎不可能調用equals方法。
-----------------------------------------------------------------------------------------------
/首先,內部類其實就是一個子類對象
//其實內部類的出現,在一定意義上實現了多繼承。因爲內部類 可以有多個,分別繼承別的類。外部類也可以用內部類裏的方法了。
//然後,關於你的問題。子類如果想繼承抽象內部類,就必須在這個類中定義一個帶有外部類對象的構造方法,並在構造方法中調用外部類.super();
代碼如下:
class Outer {
abstract class Inner {
abstract void show();
public void print() {
}
}
}
class Test extends Outer.Inner {// 如果不這麼繼承,必須導入Inner類的包。
Test(Outer out) {
out.super();
}
@Override
void show() {
}
}
兩外一種解釋:
class AbstractTest { //這裏類修飾符可以使用abstract 修飾
static abstract class A{
/* A作爲抽象類,那麼static 必須保留,做爲類靜態成員變量。 A內部類,爲外部類AbstractTest 的一個成員屬性,隨着對象的創建而加載,不能直接調用內部類,要調用只能new AbstractTest ().A。要想繼承的話,只能把內部類改成靜態內部類,static abstract class A {},此時對着類的加載而加載。*/
abstract void say();
}
void c(){
System.out.println("sss");
}
}
class B extends AbstractTest.A{
public static void main(String[] args){
}
@Override
void say() {
// TODO Auto-generated method stub
}
}
重點:非靜態內部類,伴隨着類的實例化開闢內存單元。 A抽象內部類,爲外部類AbstractTest 的一個成員屬性,隨着對象的創建而加載,不能直接調用內部類,要調用只能new AbstractTest ().A。要想繼承的話,只能把內部類改成靜態內部類,static abstract class A {},此時對着類的加載而加載。
---------------------------------------------------------------------------------
--------- javac ----------
Main.java:11: 錯誤: 需要包含Outer.InnerAbs的封閉實例
class AA extends Outer.InnerAbs
^
1 個錯誤
爲什麼會產生這樣的錯誤?
能不能修改這個錯誤,同時還能保證AA能夠繼承Outer.InnerAbs ?
-----------------------------
編譯器的意思是:要創建Outer.InnerAbs的子類對象必須保留一個外部類的引用。
原理如下:
當創建一個子類時,子類構造函數總會調用父類的構造函數,因此在創建
非靜態內部類的子類時,必須保證讓子類構造函數可以調用非靜態內部類
的構造函數,調用非靜態內部類的構造函數時,必須存在一個外部類對象,
因爲當調用非靜態內部類的實例方法時,必須有一個非靜態內部類實例,
而非靜態內部類實例必須寄存在外部內實例裏。
代碼可以修改如下:
class Outer
{
int a=90;
public abstract class InnerAbs
{
int b=80;
abstract void inAbs();
}
}
class AA extends Outer.InnerAbs
{
//顯式定義AA(非靜態內部類子類)的構造函數
AA(Outer out)
{
out.super();
}
void inAbs()
{
System.out.println("AA……inAbs");
}
}
class Main
{
public static void main(String[] args)
{
Outer out = new Outer();
//非靜態內部類子類的創建
AA aa = new AA(out);
aa.inAbs();
}
}
知識點
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.