第一篇:黑马程序员java培训就业班笔记:day10总结
Day10总结:
1、多态的特点:
1、成员变量:
当在子父类中出现了相同的非私有成员变量时,在多态调用中的特点:
在编译时:参考引用型变量所属类中是否有调用的成员变量,如果有编译通过,如果没有编译失败。
在运行时:参考引用型变量所属的类中的成员。
简单一句话:对于成员变量无论是编译还是运行都参考引用型变量所属类中的成员变量。
也就是说:成员变量看等号左边。
2、成员函数:
当子父类中出现一模一样的函数时,在多态调用中的特点:
在编译时:参考引用型变量的所属的类中是否有调用的成员函数。在运行时:参考的是对象所属的类中是否有调用的成员函数。
原因是:编译时期应该参考父类,运行时期应该参考子类。因为成员函数上有一个特点覆盖。
简单一句话:对于成员函数,编译看左边,运行看右边。
3、静态函数:
在编译时期:参考引用型变量所属的类中是否调用的静态函数,如果有编译通过,如果没有编译失败。
在运行时期:参考的还是引用型变量所属的类中的静态函数。简单一句话:对于静态函数,无论是编译还是运行都看左边
总结:对于多态成员而言,无论编译还是运行都看左边,只有成员非静态函数,编译看左边,运行看右边,因为覆盖的特性。
2、多态的应用: 代码实现:
Object:所有类的父类,该类中的方法所有对象都具备。代码实现:
Class Demo extends Object { Private int num;Demo(int num){ This.num=num;} 通常都会按照对象自身的特点对对象进行比较,比如:现在要比较两个Demo对象中null值是否相同。} Public boolean compare(Demo b){ Return this.num=d.num;
} 发现Demo继承Oject已经具备了比较对象的方法,所以没有必要再定义新的方法compare了,直接使用equals就可以了,可是Object equals比较的是地址值,不是我们所需的,那就保留的父类的功能声明,建立自身的比较内容,这就是覆盖。Public boolean equals(Object obj){ If(!(Object instanceof Deno))Return false;Demo d=(Demo)obj;向下转型。
Return this.num=d.num;此处体现了多态的特性。} Public String toString(){ Return “demo:”+num;} Class ObjectDemo { Public static void main(String[] args){ Demo d1=new Demo(4);Demo d2=new Demo(4);Sop(d1.toString());Sop(d1);Sop(c1.getName());Sop(d1.compare(d2));} }
4、内部类:
将一个类定义在另外一个类的里面的类称为内部类 当一个类要直接访问另外一个类的成员时,可以将这个类定义到另一个类里面,称为另一个类的内部类。
内部类访问的规则:
1、内部类可以直接访问外部类中的成员。
2、外部类需要创建内部类对象才可以访问内部类中的成员。
在描述事物时,事物中还有具体的事物时,而且这个内部事物在访问着外部的事物时。这时对这个内部事物的描述,就可以用内部类完成。
内部类出于外部类的成员位置上是可以被成员修饰符所修饰的。Public
Private:将内部类私有化时,只能对外提供方法,对内部类的控制。
Static:当内部类中定义了静态的成员时,该内部类必须静态的,否则编译失败。代码体现: Class Outer { Static int num=4;Static class Inner //内部类,为什么要定义内部类?
当一个类要直接访问另一个类中的成员时。可以将这个类定义到另一类里面。{ Static void show(){ Sop(“show run”+num);} Public void method(){ Inner in=new Inner();In.,show();} } } Class InnerClassDemo { Public static void main(String[] args){ //Outer out=new Outer();
//out.method();
//System.out.println(“Hello World!”);
//当访问一个外部类的内部类时,先由外部类对象再有内部类对象。
//Outer.Inner in=new Outer().new Inner();//要指明内部类所处的外部类
//in.show();
//内部类静态化,要调用的非静态的方法show();
//Outer.Inner in=new Outer.Inner();
//in.show();
//如果show方法也是静态的,要调用静态的方法show();
Outer.Inner.show();} }
5、匿名内部类:没名字的内部类。
就是内部类的简化写法。
前提:内部类可以继承或者实现一个外部类。代码实现: 格式:
New 父类名or 接口名(){子类的具体内容} Abstract class AbdsDemo { Abstract void show1();Abstract void show2();} Class Outer { Int num=4;New AbsDemo(){ Void show()//匿名内部类 { Sop(“num===”+num);} }.show();} Public void method2(){ AbsDemo a=new AbsDemo();{ Public void show1();Public void show2();};A.show1();A.show2();//要想调用两个方法,怎么做?起个名称即可
当里面有多个方法的时候建议不要写匿名内部类。
}
-----------------------------interface Inter {
void show();} class Outer {
//补足代码。最好用匿名内部类
static Inter method()//为什么是Inter类型
{
return new Inter()
{
public void show()
{
System.out.println(“show run”);
}
};
} }
class InnerClassTest
{
public static void main(String[] args)
{
Outer.method().show();
/*
Outer.method():Outer类中有一个method方法,而且这个方法是静态的。
Outer.method().show
会返回一个对象,而且这个对象还可以调用show方法
说明这个对象肯定是Inter类型。
*/
} }
------------------------------
6、异常:
是在运行时期发生的不正常情况
Java发现不正常的情况都包含着一些常见信息,并 将这些信息进行了对象的封装。异常这种机制,其实就是java按照面向对象的思想将出现的问题封装成了对象。在进行问题分析时,发现问题有很多种,但是不断向上抽取,最终问题可以归纳为两种,一种是可以针对处理的一种是通常不进行处理的。
在java中的体现一个是Exception ,一个是Error,后者一般针对处理。
无论是异常还是错误,他们都有名称信息等共性的内容。
可以继续抽取形成一个父类:throwable可抛出。Throwable
|---Error |---Exception 异常和错误都有一个特点:其子类的名称的后缀名都是父类名。
该体系具备一个特殊的特性叫做可抛性,该体系中的类可以被关键字throws抛出。
该体系中的类产生的对象可以被Throw抛出,简单说该体系可以被Throws 和throw操作。
Throw 和throws的区别:
Throws:定义在函数上,用于声明函数的可能出现的问题,后面跟异常类,可以跟多个,用逗号隔开、Throw:定义在函数内,用于抛出异常对象因为程序的跳转,后面跟的是异常对象。
If判断和异常处理的区别:
If判断是将正常代码和异常代码写在一起。阅读性极差,异常处理将问题代码和异常处理代码分离。代码实现: Class Demo { 功能的定义着在定义工呢过时,发现该功能容易因为未知内容的不确定性的出现的问题。为了让调用者明确,有可能有问题,需要在函数上对问题进行声明。
需要一关键字throw异常名。
Int div(int a,int b)throws Exception//抛出异常是为声明异常问题,让调用者去处理。{ If(b==0)Throw new ArithmeticException(“除数为零、违反规则”);
Return a/b;} } 对异常的针对性处理方式: Try { 需要被检测的代码; } Cathch(异常类 变量){ 异常处理代码 } Finaly { 一定会被执行的代码。}
自定义异常:
Java将常见的问题都封装成了对象。
对于自定义项目中出现的问题,java并未给出对应的描述,这时我们就需要按照面向对象的思想自己完成对问题的描述和封装。
自定义异常:
需求:在我的程序中,进行除法运算,除数不可以为负数也不可以为0;对0这种情况,java中有对应的描述,ArithmeticException 对于负数,java中没有。只有我们自己定义,定义一个类来对异常进行描述。
Class FuShuException extends Exception { Private int num;FuShuException(){} FuShuException(String message,int num){ Super(message);This.,num=num;} Public int getNum(){ Return num;} } Class Demo { Int div(int a,int b)throws FuShuException { If(b<0)Throw new FuShuException(“除数不可以为负数”);函数内抛出异常,函数上一定要标示。函数内抛出是什么?函数上就标示什么? 对方抛出什么异常,我就处理什么异常。Return a/b;} }
Class ExceptionDemo2 { Public static void main(String[] aths){ Demo d=new Demo(); Try
{ Int num=d.div(4,-1);Sop(“num=”+num);} Cathc(FuShuException e){ Sop();e.printStackTrace();} Sop(“over”);} }
自定义应用: 异常分两种:
1、编译被检测的异常:Exception 这种异常通常都需要进行针对性的处理。
2、运行时发生的异常:RuntimeException 对于运行时异常一般是不编写针对性的处理方式,如果该异常发生就让程序停止,对程序进行修正。因为这种的出现往往已经无法让程序继续运算了。
class Demo {
int div(int a,int b)throws ArithmeticException
{
if(b==0)
throw new ArithmeticException(“除数为零”);
return a/b;
} } class ExceptionDemo3
{
public static void main(String[] args)
{
getIndex(null,4);
}
public static int getIndex(int[] arr,int key)
{
if(arr==null)//进行健壮性判断。
throw new NullPointerException(“没有具体的数组”);
for(int x=0;x { if(arr[x]==key) return x; } return-1; } public static int getElement(int[] arr,int index) { if(arr==null) throw new NullPointerException(“没有具体的数组实例”); if(index<0||index>=arr.length) throw new ArrayIndexOutOfBoundsException(“角标越界”); return arr[index]; } }-------------------异常练习: /* 需求: 毕老师用电脑上课。按照面向对象思想来描述。名词提炼法 上课过程中出现的问题: 1、电脑蓝屏了。 2、电脑冒烟了。 */ class LanPinException extends Exception { LanPinException(String message) { super(message); } } class MaoYanException extends Exception { MaoYanException(String message) { super(message); } } class NoPlanException extends Exception { NoPlanException(String message) { super(message); } } class Computer { private int state=2; public void run()throws LanPinException,MaoYanException { if(state==1) throw new LanPinException(“电脑蓝屏了”); if(state==2) throw new MaoYanException(“电脑冒烟了”); System.out.println(“电脑运行”); } public void reset() { System.out.println(“电脑重启”); state=0; } } class Teacher { private String name; private Computer cmpt; Teacher(String name) { cmpt=new Computer(); this.name=name; } public void prelect()throws NoPlanException//此处冒烟是电脑发生的,能再老师讲课的功能出现这样的异常么?所以抛出的对象不对,老师只能耽误了讲课的进度,所以此时是否应该定义一个关于讲课进度的类来封装这个问题。 { try { cmpt.run(); System.out.println(name+“毕老师讲课”); } catch(LanPinException e) { System.out.println(e.getMessage()); cmpt.reset(); prelect(); } catch(MaoYanException e)//这个功能我处理不了,因为冒烟不会了,这时候需要抛出。 { test(); //throw e;//因为处理不了,继续往外抛。此时在讲课方法上要声明。此处也不能抛出这个异常。因为冒烟是电脑运行时的,不是老师讲课的。 throw new NoPlanException(“课时无法继续进行”); } } public void test() { System.out.println(“练习”); } } class ExceptionTest { public static void main(String[] args) { Teacher t=new Teacher(“毕老师”); try { t.prelect(); } catch(NoPlanException e) { System.out.println(“换人”); } } } //到底什么是抛什么处理? /* 自己能解决的就处理,处理不了就抛。 比如着火了,小火的时候自己可以处理,比如灭火器等 当火势大了,就处理不了,只能交给消防队,自己要跑。 */ Day05 上午: 1、数组的静态初始化 多种定义格式: Int[] arr=new int[]//标准格式,可以明确数组的数据类型,和数组名,但是不知道数组的长度 Int arr[]=new int[] Int[] arr=new int[]{2,1,3,4,5,}//通过大括号可以标示出数组中的内容,此处最好别写长度,因为容易出错,因为即初始化实体,又初始化实体中的元素。 Int[] arr={2,1,3,4,5};//可以明确数组的数据类型,和数组名,也可以知道数组中的内容。 2、arr.length:方便获取数组中的元素个数的方式。 3、操作数组的最基础的思想以及核心思想: a)最基础的思想:就是遍历。什么是遍历。 Eg:int[] arr = new int[3];int[] arr = {4,8,9,2,6,9};//明确了数组的类型和长度,并明确了数组中元素的内容。 // int[] arr1 = new int[]{4,8,9};//方便获取数组中的元素个数的方式,可以使用数组实体一个属性。length System.out.println(“len:”+arr.length); for(int x=0;x if(x%2==1) System.out.println(“arr[”+x+“]=”+arr[x]);//arr[0] = 4;} 这就是遍历的思想,获取数组中的元素,通常会用到遍历。 b)核心思想:就是操作数组中元素的角标,角标即索引,因为存数据的最终目的就是取出数据使用,就是操作角标,操作动作: 1、给数组角标上的元素赋值,2、获取角标上元素的值,存储都得用角标 4、数组中常见的操作: a)获取最值: 思路: 1、首先我们要定义一个功能完成获取数组中最大值的动作; 2、定义个函数来实现这一功能;明确结果,整数数组中的最大值,int,明确是否有未知内容参与运算,参数列表中有一个参数,数组类型int[],一定要注意这里是数组类型,不是int型; 3、如何实现功能细节呢? 1、对数组中的元素进行比较,将比较后比较大的值进行记录,并参与下一次比较,当数组中的元素都比较完成后,最大值就已经被记录下来了。 2、每次比较的较大的值不确定,定义一个变量进行记录,该变量如何初始化呢?只要初始化为数组中的人一个元素即可。 3、应该让数组中的元素自动和该变量记录的元素进行比较,所以可以使用遍 历,获取数组中的每一个元素。 4、当遍历到元素比较变量中的记录的元素大,用该变量记录住更大的元素。 5、遍历结束后,变量存储就是数组中的最大值。实现代码:eg: Public static int getMax(int arr){ /.定变量记录较大的值; Int max=arr[0];//初始化数组中的任意个元素; //对数组进行遍历比较 For(int x=1;x Max=arr[x];} Return max;} 同样有另外一种方式获取最大值 Public static int getMax(int[] arr){ Int maxIndex=0;//初始化为数组中一个元素的角标 For(int x=1;x maxIndex=x;} Return arr[maxIndex];} b)排序: 1、选择排序: 首先通过数组中元素的比较方式来分析: 用数组中第一个角标的元素与数组中第二个角标的元素进行比较,发现9比6大,进行位置置换,此处应该定义一个三方变量,用来记录住置换过程的元素值,然后再用第一个角标的元素与下一个角标元素进行比较,按照全面的原则进行置换位置,如果前者小于后者,则不置换位置,一次比较,当第一轮结束之后第一个角标出能取的该数组中最小的元素的值,然后再用第一个角标的元素开始和下一个角标的元素进行比较,同理,当第二轮结束后,第二个角标处获取了该数组中的第二小的值。所以我们发现当依次这样比较下去,就可以对数组中的元素进行排序,当比较到arr.length-1元素时,发现只剩下这一个元素,没有其他元素和它进行比较了。思路: 1、首先定义一个功能函数对数组进行排序,2、明确结果,没有返回值,因为它只是对数组进行排序的一个动作,明确是否有未知内容参与运算,有,数组类型int[] arr 实现代码: Public static void selectSort(int[] arr){ For(int x=0;x if(arr[x]>arr[y]){ Int temp=arr[x];Arr[x]=arr[y];Arr[y]=temp;} } } } 优化后的选择排序: 从上面的排序图中我们可以知道,对数组中元素进行置换位置的次数过多,也就是对堆内存的操作频繁,降低了性能,下面我们可以通过这种方式对性能优化。 思路: 在栈内存中我们定义两个变量,分别用来记录较小的元素的值和较小元素的角标,然后对其进行初始化,至于初始化的值只要是数组中的任意元素即可,然后拿数组中的元素与它进行比较,如果发现拿去比较的元素比变量中记录的数值要小,那么就进行位置置换,并记录下较小的元素的角标,依次把数组中的元素遍历完,就可以获取数组中的最小元素的值和角标,然后我们拿初始化的值和获取的最小的元素进行位置的置换,这样以来当我们获取了数组中的元素的最小的时候,堆内存中的只用操作一次位置即可,这样的就提高性能。实现代码: Public static void selectSort_2(int[] arr){ For(int x=0;x Num=arr[y];Index=y;} If(index!=x){ int temp = arr[x];arr[x] = arr[index];arr[index] = temp; } } } 注意:复习的时候添加注释 2、冒泡排序: 首先通过排序方式来分析其步骤: 通过排序方式,可以知道是用数组中的元素挨个比较,如果前面的元素的值比它下一个角标的元素大,则进行位置置换,然后再用第二个角标的元素与下一个角标的元素进行比较,同样如果下一个角标的元素比它小,则进行位置置换,这样当比较到arr.length-1个元素时已经没有 和它进行的比较的元素了,当第一轮比较结束后,我们可以知道最后一个角标的元素为该数组中的最大值,按照同样的原理进行下一次比较,依次获取了比较大的元素的值。 实现代码: Public static void bubbleSort(int[] arr){ For(int x=0;x If(arr[y]>arr[y+1]){ //位置置换 } } } } c)折半查找: 首先分析数组元素的查找方式: 首先要明确数组时有序的。 首先定义三个变量min、mid、max分来用来记录最小角标、中间角标、最大角标,中间角标的获取为(min+max)/2;获取中间角标之后,就可以获取中间角标对应的元素arr[mid];用我们所需要查找的key与中间角标运算进行比较,如果key>arr[mid];那么此时min的位置就是mid的下一个角标,min=mid+1;然后再次获取中间角标的元素,mid=(min+max)/2,同时也获取了中间角标对应的数组元素,arr[mid],然后同理,拿key与中间角标的元素进行比较.同样的原则,依次比较,直到key==arr[mid]的时候获取key.如果当出现了min>max或者时候则说明我们要查找的key在该数组中布存在,return-1; 实现代码: Public static void binarySearch(int[] arr int key){ Int min,mid,max;Min=0;Max=arr.length-1;Mid=(min+max)>>1//相当于/2,右移的效率比它要高 While(arr[mid]!=key){ If(key>arr[mid])Min=mid+1;Else if(key Min=mid-1;If(max Return mid;} 注意:复习的添加代码注释 总结:折半查找也称二分查找,这种查找可以提高效率,但是被查找的数组的额元素必须是有序的。不能对无序的数组进行排序后再用折半查找,因为这时候数组中元素的角标已经发生变化了。 5、查表法思想: a)什么时候使用查表法? 当元素很多,而且这些元素与数组有对应关系,而且这些数字都有角标的规律的时候。 扩展:什么时候使用数组? 当同一类型的元素较多时,就使用数组这个容器对数据进行存储。b)查表法思想的代码体现: 0 1 2 3 4 5 6 7 10 11 12 13 14 15 '0', '1', '2', '3', '4','5', '6',' 7', '8', '9','A',' B', 'C' ,'D', 'E' ,'F' 我们发现十六进制中一共有16个元素,而且每通过&15获取的数字都再15之内,都有对应的十六进制元素,而且元素对应的数字正好有规律,而且符合了数组这种容器的特点角标,那么可以将十六进制的元素都存储到数组中,将每次&15的结果作为角标去查这个数组,就可以获取到十六进制的对应的元素。这就是查表思想。 代码体现: Public static void searchList(int num){ //定义一个十六进制的元素表 Char[] arr={'0', '1', '2', '3', '4','5', '6',' 7', '8', '9','A',' B', 'C' ,'D', 'E' ,'F'};//定义一个char类型元素的数组,用于存储每次获取到的十六进制值。Char[] chs=new char[8];Int pos=chs.length;While(num!=0){ Int temp=num&15;Chs[--pos]=arr[temp];Num=num>>>4;} For(int x=pos;x 通过上面我们可以知道那么是否可以定义这样的一个功能函数呢?用来对十进制、二进制、八进制、十六进制进行转换? 思路: 1、明确结果,没有返回值,只是对给定的数据转换的功能。 2、明确是否有未知内容参与运算,有,是什么?求的数值num,十六进制是&15,八进制是&7,二进制是&1,那么&的这个是不确定的,我们定义为变量 base,当这个数值通过&上这些数据后,要取出后面的数值,我们通过右移来实现,但是各个进制的不一样右移的位置数也是不一样的,十六进制是无条件右移四位,八进制是无条件右移三位,二进制是无条件右移1位,所以这个数也是不确定的,定义变量 offset 实现代码: //十进制--二进制 public static void toBin(int num){ trans(num,1,1);} //十进制--八进制 public static void toOctal(int num){ trans(num,7,3);} //十进制--十六进制 public static void toHex(int num){ trans(num,15,4);} Public static void trans(int num,int base,int offset){ If(num==0){ Sop(0);;Return;} //定义一个十六进制的元素表 Char[] arr={0', '1', '2', '3', '4', '5', '6', ' 7', '8', '9', 'A',' B', 'C' ,' D', 'E' ,'F'};Char[] chs=new char[32];Int pos=chs.length;While(num!=0){ Int temp=num&base;Chs[--pos]=arr[temp];Num=num>>>offset;} For(ingt x=pos;x System.outr.println(chs[x]);} } 注意:复习的添加代码注释。 这一章节自己还不是很熟悉,能理解,但是不能独立写出代码,在以后的几天内要每天都要一遍,并自己独立写出代码,做到思想理解透彻。先要产生一天的宏观思想。复习方法: 首先总结当天学习的方法。遇到不会的先放到一边。每天晚上睡着觉之前要回忆一遍。 Day06总结: 上午 1、二维数组 格式: Int[][] arr=new int[2][3];[2]代表1维数组的个数; [3]代表1维数组有三个元素; 内存图: 分析: 通过对内存图分布可知,首先在栈内存中加载main函数,开辟空间,定义一个变量arr,在堆内存中通过New创建一个数组实体int[2],并分配其地址值为0x0045,数组元素值进行默认初始化为Null;然后把地址值赋值给栈内存中的arr.在堆内存中开辟两块空间,分别用来存放二维数组中的数组元素,分配其地址值分别为0x0056、0x0089,然后对将地址值传给二维数组中的元素,所以说对内存中二维数组存储的是一维数组的地址值。最后变量通过二维数组的地址0x0045指向二维数组。 注意:二维数组中必须指定长度、以及实体没有对二维数组进行初始化时默认为null; 2、对二维数组的遍历(大圈套小圈思想)For(int x=0;x 3、面向对象的理解: 特点: 1、面向对象就是更符合人们思考习惯的一种思想。 2、从面向过程的执行者,转变成了面向对象的指挥者 3、面向对象将复杂的事情简单化了。 其实面向对象是一种思想,是面向过程而言,将复杂的事情变的更简单了。通过把大象放到冰箱里这个列子来理解面向对象的概念 面向过程:把冰箱门打开、存储大象、关闭冰箱;强调的过程注重行为; 面向对象:冰箱.打开、冰箱.存储、冰箱.关闭;强调的是冰箱这个对象。 面试题:你怎么理解面向对象? 首先说面向对象的特点:它是一种思想,它让复杂的问题简单化,它把执行者变成了指挥者。 然后举例子来说明,最牛的就是结合实际场景来说:其实面试官你就是在用面向对象的思想在思考问题,为什么这么说?因为公司业务蒸蒸日上,需要招更多的人来完成项目,所以才在这里招聘人员,你需要找一些具备专业编程经验的人,来帮公司完成工作,那么我就是那个对象,因为我具备专业编程能力,你就是那个指挥者,指挥我来做事,至于我怎么去完成编程任务,你是不需要去知道,你只要结果了就可以了,这其实就是把你之前的工作简化了,你不必再事必躬亲了。这就是面向对象思想的体现。 同时可以结合去饭店吃饭,在家做事等等列子来说明面向对象的思想。 扩展:OOP:面向对象编程。 OOA面向对象分析。 OOD:面向设计。还有面向接口、面向框架、面向对象的语言:C++、JAVA、C# 4、在实现功能,先找java当中是不是提供好了相关的对象,没有对象自己造一个对象。比如说公司招聘人员找不到人的时,这时公司就需要自己在公司内部培养人,也就是自己造对象。 5、类和对象关系: a)类到底是什么? 类就是对现实生活中事物的描述,描述中包含了该类事物的共性内容。Class Car(){ Int num;String color;Void run(){} } 在类中定义的变量和函数都称为类中的成员。成员: 成员变量---属性 成员函数---行为 b)什么是对象? 对象就是该类事物实实在在存在的个体。 Eg:现实生活中的对象:张 三、李四 想要描述:提取对象中的共性内容,对具体的抽象。 描述时:这些对象的共性有姓名年龄性别学习java的功能。对象也可以理解为其实就是个容器,用来存储更多的数据,存储的都是每一个对象特有的数据,而类就是这些数据所属的属性。 用java语言来描述一个小汽车 描述事物:无非就是描述事物的属性和行为 属性:轮胎数、颜色 行为:运行 Eg: Class Car { String color=“red”;Int num=4;Run(){ System.out.println(color+“"+num);} } Class CarDemo { Public static void main(String[] args){ Car c=new Car();C.color=”bule“;C.num=5;C.run();m Car c1=new Car();C1.num=8;C1.color=”green“;C1.run();} } 重点:分析上述代码在内存中的分布: 复习的时候写内存分析: 6、成员变量和局部变量的区别: 1、源代码中定义位置不同: 成员变量:定义在类中,在整个类中有效。局部变量:定义在函数中,在局部范围内有效。简单一句话:作用范围不一样,成员变量作用于整个类中,局部变量作用于函数中,或者语句中。 2、在内存中的位置和事件不同: 生命周期不同: 成员变量:随着对象的创建的而出现在堆内存中,随着对象被回收而消失。 局部变量:随着变量所属局部区域的运行,而出现在栈内存中,随着所属区域运行结束而释放。 3、变量使用的初始化: 成员变量:因为堆内存中都有默认初始化值,对于引用型变量默认值就是null;局部变量:因为在栈内存中都没有默认初始化值,必须手动初始化后才可以参与运算。 7、匿名对象: 即没有名字的对象,简化书写用的。基本使用: 1、当对对象的方法只调用一次时,可以用匿名对象来完成 这样写比较简化,如果对一个对象进行这个成员的调用,必须给这个对象起个名字 2、可以将匿名对象作为实际参数进行传递。一旦对对对进行多个成员操作时。必须要对对象起个名字。 Eg: Main(){ Show(new Car())} Public static void show(Car c) { C.num=3; C.color=”back";C.run();} 8、面向对象三个特征: 封装: 是指隐藏对象的属性和实现细节,仅对外提供公共访问方式,凡是面向对象必须有封装性。 特点: 将变化隔离 便于使用 提高复用性 提高安全性 原则: 1、将不需要对外提供的内容都隐藏起来。 2、把属性都隐藏,提供公共方法对其访问。在代码中的体现: 1、将成员变量都私有化,并通过共有的方法对其进行访问,这两个方法是:setXxxgetXxx 2、只要不准备对外提供的全部都封装起来,3、私有仅仅是封装的一种表现形式,函数是最小的封装体。方法需要私有吗? Public static void selectSort(){ Swap();} Private void swap()//此处私有是因为位置置换不用提供给用户。{ } 代码实现: Class Person { Private int age;//为了不让其他程序直接访问age属性,避免错误的数据,可以使用一个关键字来完成private私有,它是一个权限修饰符。 Public void setAge()//对外提供函数是可以控制你输入的参数。//一个成员变量通常对应的两个方法、{ If(a>130||a<0){ Age=a; Speak();} Else System.out.println();} Public void getAge(){ Return age;} Void speak(){ Sop();} } Class PersonDemo { Public static void main(String[] args){ Person p=new Person();P.age=-20;//错误数据是因为对象直接访问age属性造成的。P.speak();} } 总结:之所以对外提供访问方式,就是因为可以在访问方式中加入逻辑判断等语句 对访问的数据进行操作,提高代码的健壮性。凡是set开头的返回值类型是void,get开头的跟它的返回值类型一致。 Day09总结: 上午: 1、final关键字: Eg:代码实现: Class Fu { Final void method(){ //code...访问低层代码 } } Class Zi extends Fu { Void method() { Sop(“haha”);} } 以上代码体现出继承的弊端,因为父类的method的方法访问了系统的低层代码。当子类对其覆写,就不会去访问父类的meth的方法,直接用自己的method这样就出现了代码的不严谨性,所以此时需要用final关键字进行修饰。注意为什么不把类加final修饰,因为可能该类中会出现很多功能。有些是不需要被覆写的。有些是被调用的。所以只能根据自己所需对相应的成员进行修饰。 2、Final的特点: 1、final是一个修饰符,可以修饰类、方法、变量(成员变量、局部变量) 2、Final修饰的类不可以被继承。 3、Final修饰的方法不可以被覆盖。 4、Final修饰的变量是一个常量,只能被赋值一次。是为了增强阅读性,只要数据是固定的,就将这个数据用一个名称来表示,并用final修饰。常量名称都是大写字母,多个单词组成时用下划线来分隔。 代码体现: Eg: Class Zi { Static final int num=90;//必须对变量进行初始化,不知道要最终化哪个值,所以必须对它进行初始化。加静态也是一样的,同样的道理,并且被初始化,此时静态和final没有必然的联系。当变量被final修饰时,说明变量已经是一个常量值,此时不能被修饰,可以用static来修饰。 Public stati double PI=3.14;Void method(){ Final int x=4; X=8; Sop(num);//既然是在操作一个固定的值。为什么不把4直接写在此处,如果这样做的的话,阅读性极差,你根本就不知道它所代表什么?为了增强阅读性,此时数据是不变化的,所以我们需要给它起个名字,并且用final来修饰。这样的话它也是固定的不变的。 注意:被final修饰的数值只能被覆写一次,并且修饰的常量名全部大写,多个单词组成时用下划线进行分隔。Eg:final int PERSON_AGE=4;} } 3、抽象类: 特点: 1、没有方法体的方法,称为抽象方法,必须存放在抽象方法类中,抽象方法和抽象类必须用abstract关键字来修饰,2、抽象类不可以被实例化,为什么?因为调用抽象方法没有意义?为什么?因为它连方法体都不存在? 3、抽象类必须由其子类将抽象类中的抽象方法都覆盖后,其子类才可以被实例化,否则该子类还是抽象类。Eg: Abstract class Demo { Abstract void show();} Class SubDemo extends Demo Void show(){} //此时把父类中抽象方法覆盖,此时才能被实例化。} 比如水果,它就是抽象的,不具体它包含各种各样的水果,每种水果有它自己的体现。 抽象类涉及的问题? 1、抽象类中是否可以定义非抽象的方法? 可以 首先抽象类是一个类,类是用来描述事物,只不过描述事物过程中有些信息不具体,抽象类和一般类异同点: 相同:抽象类和一般类都用于描述事物,都可以定义成员。不同:抽象类中可以定义抽象成员函数,(抽象要么修饰类要么修饰函数)而一般类不可以。 抽象类不可以实例化,一般类可以实例化。 2、抽象类中是否有构造函数? 有,而且抽象类虽然自身不可以被实例化,但是其子类覆盖了所有的抽象方法后,是可以实例化的。所以抽象类的构造函数是用于给其子类对象进行实例化。 3、抽象类通常都是一个父类? 是、因为需要子类去覆盖父类中的抽象方法。代码体现: Abstract class Demo{ Abstract voif show1();Abstract void show2();} Abstract class SubDemo extends Demo { Void show1();} Class Test extends SubDmeo { Void show2();} 4、抽象类中可不可以不定义抽象方法? 可以;看上去没有什么意义,其实有点意义,就是不让这个类创建对象,为什么不让创建? 代码体现: interface InterTest//这是一个测试接口,有4种测试方式。 { void test1();void test2();void test3();void test4(); } abstract class InterTestImpl implements InterTest//用这个类进行所有的空实现。但是创建对象是毫无意义的。所以用抽象。 { public void test1(){} public void test2(){} public void test3(){} public void test4(){} } class Test2 extends InterTestImpl { public void test2(){} } class Test3 extends InterTestImpl { public void test3(){} } /* class InterTestImpl implements InterTest { public void test2()// { sop(“testimpl test2”); } public void test1(){}//这样做实现太麻烦。代码重复。如何改进? public void test3(){} public void test4(){} } */ 5、抽象关键字 不可以和那些关键字共存? Final:修饰了类是一个最终类,不可以被继承,然后abstract修饰的类必须是父类,需要被继承、冲突、非法的修饰符组合,abstract 和final Static:抽象方法被static修饰,就具备了可以被类名直接调用的的特点,但是抽象方法被调用没有意思。 Priavte:因为抽象方法被私有,无法被覆盖。 代码体现: 雇员实例: 需求:公司中程序员有姓名、工号、薪水、工作内容。 项目经理除了姓名、工号、薪水、还有奖金、工作内容 进行数据建模 做问题领域的分析就是找出问题领域的对象。 分析: 在这个问题领域中有两个对象: 程序员: 属性:姓名,工号,薪水 行为:工作内容 项目经理: 属性:姓名、工号、薪水、奖金 行为:工作内容。 这时候不能用项目经理去继承程序员。因为职能不同,但是有共性,只能抽取。 就有了员工: 属性:姓名,工号,薪水 行为:工作内容 */ abstract class Employee { private String name;private String id;private double pay;Employee(String name,String id,double pay){ this.name=name; this.id=id; this.pay=pay;} public abstract void work();//工作内容是无法知道的。} class Programmer extends Employee { Programmer(String name,String id,double pay){ super(name,id,pay);} public void work(){ System.out.println(“code”);} } class Manager extends Employee { private double bonus;Manager(String name,String id,double pay){ super(name,id,pay); this.bonus=bonus;} public void work(){ System.out.println(“manage”);} } 4、接口: 格式:interface{} 表现特点: 1、里面的方法都是抽象的。 2、接口中的成员都有固定的修饰符,最常见的成员:全局常量抽象方法。只是最常见,不代表只有它们没有其他的,全局常量,共有的不需要对象,直接用接口调用的,不可变的。 表现形式:Public static final 抽象方法:public abstract 3、接口的成员都是public的。 4、接口是不可以创建对象的。就相当于是抽象的特殊表达形式。(但是有区别和抽象类) 5、类与类之间是继承关系,类与接口之间是实现关系。 6、接口的出现可以多实现,避免了单继承的局限性。 7、一个类在继承一个类的同时,还可以实现多个接口、8、接口与接口之间是继承关系,而且可以多继承,以为接口的方法都没有主体。思想特点: 1、对外暴露的规则。 外设要介入计算机中,因为计算机外面提供了接口,这就是规则。 2、程序的功能扩展 3、降低了耦合性 4、用来多实现 结合电脑主板的思想进行阐述,它是个规则。对外提供的规则 它提高了我们功能的扩展性,降低了耦合性。主板和声卡:主板使用规则,声卡实现规则。 与抽象类的区别:抽象类有单继承的局限性,接口没有 5、java对多继承记住改良,以多现实接口的方式来体现。差别:多继承因为父类中有相功能时,会造成不确定性。为什么可以实现多实现? 因为继承中父类的方法有方法体?这才是造成不确定性的根本原因,而此处是没有方法体的。 代码体现: interface A { //int show();//这样是不可以的。无法覆盖。 void show();} interface B { // void method(); void show();//当有重复的方法时。但是此时子类复写它是可以的,为什么? //因为继承中父类的方法有方法体。这才是造成不确定性的根本原 因。而 //此处是没有方法体的。 } class C extends D implements A,B//多实现。此时c必须覆盖两个方法 { public void show(){} //public void method(){} } //一个类在继承一个的类的时候还可实现多实现 class D { public void function();} //接口之间是可以继承,而且支持多继承。 interface InterA { void showA();} interface InterB { void showB();} interface InterC extends InterA,InterB//为什么此处可以实现多继承,因为方法没有主体。 { void showC();} class InterfaceDemo2 { public static void main(String[] args) { C c=new C(); c.show(); System.out.println(“Hello World!”); } } 6、抽象类和接口之间的区别: 共性:它们都是不断抽取出来的抽象非概念 区别: 1、抽象类只能被单继承、接口可以被多实现,避免了单继承的局限性。 2、抽象类中可以定义抽象方法,和非抽象方法,它可以用于定义体系的基本共性的内容。接口中只能定义抽象方法,它主要用于对象的功能的扩展。 3、抽象类是继承关系,是is a关系,接口是实现关系是like a关系。 4、抽象类中的成员修饰符都是自定义的,接口中的修饰符都是固定的。记住:不要把接口狭义的理解为interface,应该理解广义些,就是对外提供的规则,凡是对外暴露的都可以是接口。 实现代码: 1、abstract class 犬 { public abstract void 吃饭(); public abstract void 吼叫(); } interface 搜爆 { public void 搜爆(); } class 搜爆犬 extends 犬 implements 搜爆//这是即具备了犬的基本特性,又具备了搜爆功能。 { public void 搜爆(){} public void 吃饭(){} public void 吼叫(){} } class 搜爆猫 extends 猫 implements 搜爆 { public void 搜爆(){} } 记住: 类里面都是定义的一些基础内容,接口里面都是定义一些特性内容,这样的方便了对其进行扩展。 //抽烟的学生,抽烟是额外功能。 2、abstract class Student { abstract void study(); } interface Smoking { void smoke(); } class SomkeStudent extends Student implements Smoking { public void study(){} public void smoke(){} } //烟民。学生烟民 问题领域不同,对象的属性和行为也不同。 abstract class Somker { abstract void smoke(); } interface Study { void study(); } class StudentSmoker extends Smoker implements Study { public void smoke(){} public void study(){} } 7、多态:重点掌握 定义:某一类事物的多种存在形态。代码实现: class 动物 {} class 猫 extends 动物 { } 猫 x=new 猫(); 动物 y=new 猫();//父类的引用变量指向了其子类的对象。 多态在代码中的体现,父类或者接口的引用指向了自己的子类对象。 实现代码: class Animal { abstract void eat(); } class Dog extends Animal { void eat(){ sop(“啃骨头”);} void lookHome() { sop(“看家”);} } class Cat extends Animal { void eat(){ sop(“吃鱼”);} void catchMouse(){ sop(“抓老鼠”);} } class Pig extends Animal { void eat(){ sop(“猪饲料”);} void gongdi(){ sop(“拱地”);} } class DuoTaiDemo { public static void main(String[] args){ //Cat c=new Cat(); //c.eat(); //Cat c1=new Cat(); //c1.eat(); //method(c); //method(c1); 重要知识点:----开发都用! Animal a=new Cat();//此处猫对象类型自动向上提升---向上转型,当指向使用体系基本功能时,可以向上转型操作。 为什么体现多态性? 首先猫是一个实体,是一个猫类型,因为有了继承,是动物中的一种,把这个实体称之为动物也可以,所以它具备了两种形态,猫和动物。这便是体现了多态性。 //一旦向上转型,猫就不是猫了,已经是动物类型了。 a.catchMouse();//编译失败。 但是现在想执行猫的抓老鼠的功能怎么办? 向下转型: Cat c=(Cat)a;//向下转型。当使用子类对象中的特有内容时,才做向下转型。 c.eat(); c.catchMouse();//此时是可以实现猫的抓老鼠的功能的。 总结:在多态转型中,至始至终只有子类对象做着类型的变化。 method(new Cat()); } public static void method(Animal a)//Animal a=new Cat();{ 重点知识点:instanceof if(a instanceof Cat)//对象instanceof 类型 判断具体对象是否是指定的类型。 { Cat c=(Cat)a;//编译通过,但是不能运行,此时类型转换异常classCastException; //此时为了程序的严谨性,需要对传入的的对象进行判断。 c.catchMouse(); } else if(a instanceof Dog) { Dog d=(Dog)a; d.lookHome(); } a.eat(); 总结: instanceof是一个关键字,用于判断对象的类型。什么时候用? 当进行向下转型时,先判断该对象是否符合被转成的子类型。 } } 8、重点理解: 1、多态的好处:提高了代码的扩展性,有了多态,前期设计好的内容可以使用后期出现的子类内容,对于指挥对象做事情这件事情,如果对象很多,指挥起来很麻烦,抽取对象的共性类型,对该类型的事物进行指挥就会变的很简单。 2、多态的前提: 1、必须要有关系:继承、实现。 2、必须有覆盖的操作。 3、多态的弊端:前期的程序虽然可以使用后期出现的子类内容,但是只能使用子类覆盖父类中的内容,不能使用子类中的特有内容。 Day14总结: 1、wait和sleep的区别:(面试题) 1、sleep指定时间,wait可以指定时间,也可以不用指定时间。 2、wait方法必须定义在同步中,sleep方法不一定。 3、在同步中wait sleep对于执行权和锁的处理不同: i.Sleep释放CPU执行权,但是没有释放锁。ii.Wait释放执行权、释放锁。实现代码: Public void run(){ Synchronized(this){ Code…sleep(10);//此线程进入冻结状态,释放了执行权,并没有释放锁。 Wait();//等待状态下,释放执行权、释放锁,因为它需要被对象唤醒,所以要释放锁 } } Public void method(){ Synchronized(this){ notifyAll();//唤醒上面所有的线程。但是此时t0、t1并没有执行,因为锁还在此线程中,只有当它执行完毕之后,释放锁。它们获取锁之后才有机会执行。 } } 2、停止线程: 1、Stop方法已经过时,为什么?因为该方法具有不固定的安全性。 如何停止线程? 只有一种方法: 线程执行的代码结束,线程会自动终止。 1、run方法中通常有循环,所以只要循环结束即可。所以只要控制循环条件。最简单的方式就是定义标记。 2、如果run中有同步可以让线程出现冻结状态的方法,比如wait那么线程就不会去读取标记。这时必须让线程恢复到运行状态才可以有机会读取到标记,所以通过正常的恢复方法比如notify、sleep时间到,但是如果没有办法正常恢复,就必须使用强制手段,interrupt方法,强制将线程的冻结状态清除,让线程恢复运行。其实就是让线程重新获取读取标记、结束。但是别忘了强制动作会产生异常要处理。实现代码: StopThreadDemo.java class StopThread implements Runnable { private boolean flag=true;//定义标记控制住循环。public synchronized void run(){ while(flag)//开始true、此时定义标记控制循环。 { try { wait();//当存在同步时,wait方法不会让线程去读取标记。此时主线程结束了,但是这两个线程却在这里等待了。并没有结束。 } catch(InterruptedException e) { System.out.println(Thread.currentThread().getName()+“....Exception”); setFlag();//如果发生了强制中断,只要把状态切断到假。 } System.out.println(Thread.currentThread().getName()+“...”);} } public void setFlag(){ flag=false;} } class StopThreadDemo { public static void main(String[] args){ StopThread st=new StopThread();Thread t1=new Thread(st);Thread t2=new Thread(st);t1.start();t2.setDaemon(true);//标记成了守护线程。 t2.start(); for(int x=0;;x++){ if(x==50) { st.setFlag(); t1.interrupt();//t1将它的冻结状态强制结束。 t2.interrupt();//中断方法。其实不是中断线程。而且还抛出了异常。 //其实会将冻结中的线程强行恢复到运行状态,就会读到标记。这就是中断线程。并不是结束线程。一定要注意要区分。 // break; } System.out.println(Thread.currentThread().getName()+“....”);} System.out.println(“Hello World!”);} } 3、守护线程:setDaemon();线程标记,守护线程,当正在运行的线程是守护线程时,JVM自动退出,该方法在开启之前调用,也就是说在start方法之前调用。 线程分两种: 前台线程:自己创建的线程都是前台线程。 后台线程:一旦调用了此方法为守护线程之后的线程都是守护线程。 区别:都是线程,启动后都再抢夺CPU的执行权,这里是没有区别的,最大的区别就是如果线程结束了,正在运行的后台线程也随着结束,简单的说后台线程是以来前台线程而执行的。 4、线程细节: 1、join:当A线程执行到B线程时,那么A线程就会等待,等B执行完毕,A才会执行。 代码实现: D1.join();d1加入,说明了主线程必须先释放执行权给它,等到d1结束之后主线程才恢复执行状态,所以输出结果是等d1全部都执行完毕之后,才有其他线程的交替执行。 记住:谁把执行权给了谁,就只和给的对象的执行权有关,等它结束之后,就会重新获取执行 记住:主线程是因为谁放弃了执行权,就只和那个线程有关系权,与其他线程无关。 2、优先级:代表抢夺资源的频率。有两种方法:getPriority setPriority来获取优先级和设置优先级,只有十个数字可以使用1-10这十个数字,同时线程中提供了几个特殊的方法: 线程类中提供了MAX_PRIORITY MIN_PRIORTY NORM_PRIORTY。 3、yield:结束该线程,释放执行权。 4、toString();获取线程详细信息,包括线程组、线程名、所属线程。实现代码:ThreadMethodDemo.java 5、string类: 1、字符串的特点: 1、java中用String类来描述字符串。 2、字符串是一个特殊的对象,一旦初始化就不可以被改变,因为是常量。面试题1: String s=“abc”;String s1=new Strng(“abc”);是否相同? 前者“abc”是一个对象。后者是两个对象,new string()代表一个对象,“abc”也代表一个对象。 Sop(s1==s2);==比较的是数据。false Sop(s1.equals(s2));比较的是内存的地址值,equals覆写了Object类中的equals方法。True 面试题2: String a=“abcd”;//在缓冲池创建了一个abcd的字符串。String a1=“ab”;//a1和a2都是变量,无法确定。 String a2=“cd”;String b=a1+a2;//b是要重新进行分配的。 String c=“ab”+“cd”;//两个都是常量值,用连接符连接在一起还是字符创。abcd System.out.println(“a==b:”+(a==b));//false System.out.println(“a==c:”+(a==c));//true 2、常见操作方法: 1、获取: a)获取长度: Int length();数组长度是个属性,字符串是个方法 b)获取字符串中的字符: charAt(int index);返回值是一个字符。 c)一个字符或者一个字符串在一个字符串中的位置 Int indexof(int ch)Int indexof(int ch,int fromIndex)Int indexof(ch,fromIndex)Int indexof(srting,fromindex)Int lastIndexof(ch);注意:这些获取索引位的方法,如果没有查找的内容,返回-1,所以这个方法。 d)获取部分字符串: String substring(begin,end) 2、判断: a)是否包含指定的字符串 Boolean contains(String) b)是否是以指定的字符串开头 Boolean startsWith(String)c)是否是以指定的字符串结尾 Boolean endwith(String)d)忽略大小写判断字符串 Boolean equalsIgnoreCase(string) 3、转换: a)将字符串转成大小写 String toLowerCase();String toUpperCase();b)将字符串转成数组 Byte[] getBytes();Char[] getChar();c)将字符串转成字符串数组 String[] d)将字符串中的内容进行替换 String replace(oldch1,new ch2)String replace(string1,string2)e)去除字符串两端的空白 Trim();如何查阅API文档的小技巧,先查找返回值类型,缩小查找范围。实现代码: ublic static void main(String[] args){ // stringMethod4(); String str = “ ab c ”; System.out.println(“-”+str.trim()+“-”); String s = String.valueOf(4); System.out.println(4+“"); System.out.println(”ab“+”cd“); System.out.println(”ab“.concat(”cd“)); } private static void stringMethod4(){ String str = ”lisi.wangwu.zhaoliu“; } String[] strs = str.split(”.“);for(int i = 0;i < strs.length;i++){ System.out.println(strs[i]);} str = ”hello“; String s = str.replace('a', 'k'); System.out.println(”s=“+s);System.out.println(str);private static void stringMethod3(){ String str = ”aBCd“; String s = str.toLowerCase();System.out.println(s);String s1 = str.toUpperCase();System.out.println(s1); System.out.println(str); char[] arr = str.toCharArray(); for(int x = 0;x System.out.println(arr[x]);} } private static void stringMethod2(){ String str = ”ThreadDemo.java“; System.out.println(”contains(Demo):“+str.contains(”Demo“));System.out.println(”starsWith(Thread):“+str.startsWith(”Thread“));System.out.println(”endsWith(.java):“+str.endsWith(”.java“));System.out.println(”isEmpty:“+str.isEmpty());str = ”abc“;说 System.out.println(str.equalsIgnoreCase(”abC“));} private static void stringMethod(){ String str = ”abcdaef“;System.out.println(”length;“+str.length()); System.out.println(”charAt(2):“+str.charAt(2)); System.out.println(”indexOf(a):“+str.indexOf('a',2)); System.out.println(”lastIndexOf(a):“+str.lastIndexOf('k')); System.out.println(”substring(1,3):"+str.substring(0,str.length()));}第二篇:黑马程序员java培训就业班笔记:day05总结
第三篇:黑马程序员java培训就业班笔记:day06总结
第四篇:黑马程序员java培训就业班笔记:day09总结
第五篇:黑马程序员java培训就业班笔记:day14(多线程、String类)总结