找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5769|回复: 0
打印 上一主题 下一主题
收起左侧

Java自学心得摘要(Java4Android版1-22集)终止这套视频

[复制链接]
跳转到指定楼层
楼主
ID:71922 发表于 2015-1-10 22:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
======================================= 华丽的分割线 ====================================2013-12-28 日 更新

我之前有看过孙鑫的JAVA视频,虽然只看了前三集,但是孙鑫老师的视频是压缩讲的,一个视频两个半钟,设计到的知识点很多,
前三个视频已经包含了《Java4Android》这套视频前二十三集的内容,而且讲的都是原理性的知识。只是孙鑫老师讲的比较死板,
举的例子不够生动。而 《Java4Android》mars老师讲的很生动,可惜都是表面性的东西,例如他的第十七集,对于静态变量、
静态函数的为什么不创建对象就能调用的解释。而孙鑫老师在第二集中讲的很明确。关于第十七集的心得就是看了孙鑫老师才知道的。

虽然说Java不是我日后的方向,但是既然日后会用上,现在又恰好在学,即使不精通JAVA也要达到熟练的程度吧?不然日后还怎么学
安卓编程。 所以我决定放弃《Java4Android》重学孙鑫老师的JAVA视频。日后发布的也发布的也将是学孙鑫老师JAVA视频的学习笔记。

唉,悲剧,这两套视频的教学思路不同,知识点的解析而理解也不同,只能重新学孙鑫老师的了。

翻到下面就能看到第21-22集的笔记。

======================================= 华丽的分割线 ====================================


这学期工作太忙,学单片机的时候总是被中断,让我很不爽。后来越来越忙就没有再学了,这段时间还算缓下来了,不过我不想再在我非常认真学单片机的过程中被频繁中断,想着日后会用到安卓手机控制单片机,由于学安卓编程需要有JAVA基础,就先接触一下JAVA基础知识,就当充实充实自己的业余生活。
本文记载一些心得中的重点部分,仅用于增强记忆和日后复习使用。
       视频教程来源:Java4Android系列视频教程 网址:http://www.marschen.com/forum.php
       这视频不错,讲的很生动。搞的我看的就像是看电影一样总想一直看下去,缺点就算说的太详细了。。。
第1集至第3集 讲的是Java的一些历史和一些基本的概念,如JDK、JRE、JVM这些。
       这里有必要说一下,Java之所以能实现跨平台是因为JVM虚拟机的存在。我们写的源代码(.java)不需要关心它会在什么平台下执行,它会被编译成中间文件(.calss),而这个中间文件是和平台无关的,主要是给JVM解释执行的。只要该平台支持JVM,那么也就支持Java了,每一个平台下的JVM都不一样,但是它们都可以解释并执行中间文件。Windows平台有Windows平台的JVM,Linux有Liunx下的JVM,说白了,只要能在某一平台下设计出支持该平台的JVM,那么该平台就可以全面支持Java了,而JVM的设计是由Java公司自己完成,我们不需要关心。这就是Java跨平台的秘密。
第4集:
有意思的变量解释:(之所以提出来是因为该视频讲的很有意思)
1、计算机是一种极度精确的机器,容不得半点马虎。
2、它很笨,要计算数据时,首先要指定数据存储在内存的位置以及空间大小。
基于上述两点,将一些常用的数据类型都固定大小,如整型(int)占用4个字节,字符型(int)占用2个字节,byte型占用1个字节等等,之所以整出这些基本数据类型都是为了方便写程序,例如你要存放一个 1025 数值或者你要存放一个字符“梦”,就不需要自己指定要申请多大的内存空间了。
       变量的声明含义:
              int       age;
       int:变量类型,也就是指明空间大小
       age:变量名,存放在内存中的位置标识,这里具体放在哪个位置由系统负责,系统分配好空间后会将该位置与我们的变量关联起来,相当于给这个位置起一个名字,我们要把数据存放到age,就表明把这个数据放到age所在的内存空间位置.
       后面的分号是标识这条语句已经结束。
第5集到第11集 主要是一些基本的程序流向控制 如判断语句 分支语句 循环语句等。
第12集至第15集 主要面向对象的一些概念:
       这集主要解释什么是面向对象。
       这集给我的冲击很大,以前我是用C语言写代码,使用的面向过程的思维去设计程序。面向对象对于我来说是一个全新编程思维。
       刚接触这种思维,可能是因为以前习惯性用面向过程的思维去设计程序,现在有些转不过弯来。
1、首先确定谁来做,其次确定怎么去做。
2、首先考虑全局,再考虑局部。
3、首先考虑抽象,再考虑具体。
如:
我们用面向对象的思维去给一栋建筑设计一座电梯。首先我们先抽象有这个电梯,然后这个电梯有高度、宽度、有门、有按键的属性,它还会有开门、关门、上升、下降等行为。确定好这些后,那么再考虑开门的方法(行为),这门要在什么时候开,怎么开才安全,门在什么时候后关,怎么关才安全,电梯什么时候上升、什么时候下降,怎么上升、怎么下降,要上升或下降到第几层等这些行为(这时候相当于定义好这个类)。定义好这些后,再根据这栋建筑去具体化这个电梯,例如这建筑有几层楼,每层楼高度是多少等,这关乎电梯的上升、下降的高度等。(这个时候相当于引用电梯这个类创建出这个对象,并初始化这个对象的一些参数)。不同的建筑需要具体化合适这栋建筑的电梯。
第13集 类和对象
       类是抽象的,对象是具体的。
类里面有状态、行为。
类里面的变量就是记录状态,而里面的函数则是行为(方法)。
举个例子:
类相当于是指明狗这种种类的一系列特征:身高、体重、毛色等一些属性,还有怎么吠叫、怎么吃饭等一些行为。它是一个抽象的东西,就好像我们说到狗,脑子里面就会想起狗的这些特征,满足这些特征才会被我们认为是狗,但并不具体到是哪一种狗,哈巴狗?藏獒?还是流浪狗?它们都是狗。
而对象则是具体到哪一种狗,藏獒和哈巴狗叫的声音不太一样,跑的也不一样,喜欢吃的食物也不同。
类和对象就好像我们需要一条狗(狗这种种类),这就选择了狗这个类。至于是什么狗,要看自己的需求,假设我们要一条藏獒,那么它应该是很彪悍的,发出的叫声应该是让人很害怕的。那么这时候我们创建这个类的对象,设置这只狗的身高、体重、毛的颜色等一些属性,然后我们要这只狗吠叫,就使用里面吠叫的方法。
定义类的方法:
Class 类名
   属性;—> 属性也叫成员变量,用来描述类的状态,如上面狗的身高、体重、毛色等。
   方法;—> 方法也叫成员方法,用来描述类的行为,如上面狗的吠叫,吃饭等。。。
生成对象的方法和流程。
例:Dog       dog = new Dog();
Dog       dog:系统会在栈内存空间创建Dog的一个引用名,为dog。
new Dog():系统会在堆内存空间创建Dog的一个对象。
=:赋值号就是把在堆内存空间创建的Dog对象关联到dog 这个引用名。
当我们使用的时候就是需要用引用名去操作这个对象。


第14集:

下面这个例子很形象的表现出类与对象的关系。

class Dog                            // 定义狗这一类
{
String       Zhonglei;              // 狗的品种
String       name;              // 狗的名字
int              age;                     // 狗的年龄
String       color;              // 狗的毛色
String       Xingbie;              // 性别
void jump()
System.out.Println(“跳啊跳啊。。。我拼命跳。。。”);
}
class Test
{
Public static void main(String args[])
{
Dog              Mydog = new Dog();              // 创建一只狗
Mydog.Zhonglei        =  “牧羊犬”;              // 我喜欢这品种
Mydog.name        =  “小黑”;                     // 这狗就叫小黑吧。
Mydog.colcr  =  “黑色”;                     // 它的毛色是黑色的
            Mydog.age       =  1;                            // 它1岁了
Mydog.Xingbie       =  “雄性”;              // 公的
Mydog.jump();                                   // 这只1岁的黑色小黑跳起来了。
Dog              Mydog1= new Dog();       // 小黑太孤单了,给它创建个伴侣吧。
Mydog.Zhonglei        =  “牧羊犬”;
Mydog.name        =  “小白”;                     // 这狗就叫小白吧。
Mydog.colcr  =  “白色”;                     // 它的毛色是白色的
            Mydog.age       =  1;                            // 它也是1岁。
Mydog.Xingbie       =  “雌性”;              // 母的
Mydog.jump();                                   // 这只1岁的白色小狗也开心跳起来了。
}
}
用着这种设计思想,感觉自己就像是上帝,哈哈。
Mydog 和 Mydog1 都是狗,但它们不是同一只狗,而是两只不太一样的狗。像上面的例子,还可以再创建一只藏獒(创建对象),藏獒和牧羊犬都是同一个物种,但却不是同一个品种。很灵活。 Dog就是抽象的,而创建的对象则是具体的。就上面的例子来说,栈空间内会存放两个对象名,堆空间内存放着两个对象。
匿名对象:
如:new Dog().jump();              
因为没有给引用名,所以它是一次性的,不知道匿名对象算不算是创建了一只狗又扔了它。。。真狠心。。。。。

第15集:
函数重载:一个类中的有多个函数名一样,但参数数量、类型不同的函数。系统会根据我们所传递的参数去判断我们要调用的是哪一个函数。
构造函数:必须和类名相同,利用函数重载,可以有多个构造函数。构造函数会在new创建一个对象时自动被调用,调用哪个构造函数取决自己new 类名(参数)所传递的参数,一般用于给成员变量赋初始值。如果没有写构造函数,编译器会自动添加一个无参数、无函数体的空构造函数。构造函数是木有返回值滴。
第16集 (this的作用和使用方法)
this(参数):调用本类中构造函数,只能写在函数中的第一句。
this.变量:在函数中访问本类中的变量,一般区分函数中有和类中同名的变量。
this.函数:调用本类中的函数。
第17集(关于静态 static)
静态变量和静态函数可以在不new(创建)对象的情况下直接调用。
例:
class Test
{
static int i ;
static void fun()
{
System.out.println(“static fun Run....”);
}
}
class main
{      
public static void main(String args[])
{
Test.i = 10;
Test.fun();
}
}
被声明为static的变量或函数都会在该类被装载时会被创建在堆栈里。也就是说不需要我们new,内存中已经有它们的存在。而且它们都是被所有这类的对象所共享。
静态变量或静态函数,之所以可以在未用new在堆空间里创建新的对象时,却仍可以通过类名使用,是因为它在程序运行时已经在堆内存分配好空间,也就是说无论有没有new,那空间都已经分配好并且不会变动。
  如视频中的例子:在Person类里面的static int i; 在类第一次被装载时 i 这个变量已经在堆空间分配好并且不会变动,所以当我们使用这个静态变量时不需要重新new对象,即使new了对象,也不会再为它在堆空间重新分配内存,无论我们new了多少个Person对象,它们都是共享同一个 i 空间。所以当改动 i 的值时,自然而然的看起来是像影响到其他对象里面 的 i 值。
而 int i;这种非静态变量则必须是在调用new时才会在堆空间分配好内存。而且每次new的空间位置都不一样,都是一份拷贝,每一份拷贝都关联不同的Person对象,这样就变成即使修改了第一个Person对象里的i,也不会影响第二个Person对象里面的i。

关于匿名静态函数:
匿名静态函数没有名字的函数。
static
{
System.out.println(“我是匿名静态函数”);
}
匿名静态函数在使用类的时候会被调用,而构造函数则是在new时被调用。
1、Test.i = 10 或 Test.fun()    匿名静态函数会被调用
2、Test t = new Test()                 匿名静态函数会被调用后,构造函数才会被调用。

第18集 继承
通过关键字 extends 来继承某一类,被继承的类为父类,继承的类为子类。
子类拥有父类所有的成员变量和成员函数,但不拥有构造函数。
子类可以有自己的成员变量和函数,感觉是在父类的基础上是增加状态和行为。是父类的一种扩展。
例子:
class myzl extends Gog              // myzi 是子类的名字,Gog是父类,是已经存在的类
{
}
第19集super关键字
由于子类是不能继承父类的构造函数,所以可以使用super这个关键字去调用父类的构造函数,当然这个super不但可以调用父类的构造函数还可以在父子类之间函数名、变量相同的情况下,在子类调用父类的函数或访问父类的变量。super和this差不多,都是用于区分同名函数或变量。
super() :调用父类的无参构造函数
super (参数):调用父类的有参构造函数
super和this的异同:(网上资料)
  1)super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
  2)this(参数): 调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
  3)super:它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员                数据或函数,基类与派生类中有相同成员定义时如:super.变量名,super.成员                函数据名(实参)
  4)this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;   
          如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
  5)调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法
      的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么
      在编译的时候就会报错。
  6)super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内
      调用其它方法。
 7)super()和this()均需放在构造方法内第一行。
 8)尽管可以用this调用一个构造器,但却不能调用两个。
 9)this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,
       其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同
       的语句,就失去了语句的意义,编译器也不会通过。
  10)this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变
        量,static方法,static语句块。
 11)从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。



第20集
函数的override(覆盖、重写)
需要满足两个条件:
1、在具有父子关系的两个类当中。
2、父类和子类都有一个同定义的函数(返回值类型、函数名和参数列表等完全相同)
当父类中的某A函数完全无法满足我们的要求时,我们可以在子类上重写父类的A函数,这个A函数会完全覆盖父类的A函数,当执行A函数时,父类的函数是不会被执行的。
当然,很少情况下会遇到父类A函数完全无法满足我的要求,若是遇到还不如重新写一个函数。当然,如果是修改以及完成的源码,因为后面的代码已经写好调用了这个A函数名,那么这时候我们可以重写A函数,而不必要修改后续的代码调用。
一般遇到的是父类的A函数能满足一些基本的要求,但还是缺少一些功能,这时候我们可以先通过super.A() 来直接调用父类的代码,然后下面再添加需要的一些功能,这样当子类的A函数被调用时,会执行super.A(),而super.A()会是调用父类的A函数,那么父类的A函数执行完后就会执行接下来我们写的代码了。
例:
class Person
{
       String name;
       int age;
      
       void OutMsg()
       {
              System.out.println("父类 OutMsg");
              System.out.println("我的名字是" + name + "我的年龄是" + age);
       }
}
class Student extends Person
{
       String address;
      
       void OutMsg()
       {
              // 若这里是和父类的代码一样则可以换成 super.OutMsg();
              // 这样就可以直接调用父类的OutMsg函数,避免重复代码
              System.out.println("子类 OutMsg");
              System.out.println("名字是" + name + "年龄是" + age);
              
              // 这是子类新增加的代码
              System.out.println("我的地址是" + address);
       }
}
class Test
{
       public static void main(String[] args)
       {
              Student s = new Student();
              
              s.name = "张三枫";
              s.age = 20;
              s.address = "广东";
              
              s.OutMsg();
       }      
}
输出:
D:\MyJava>javac *.java
D:\MyJava>java Test
子类 OutMsg
名字是张三枫年龄是20
我的地址是广东

================================================ 华丽的分割线 ================================================
2013-12-28 日 更新
[color=#3306f9,strength=3)"]================================================ 华丽的分割线 ================================================[color=#3306f9,strength=3)"]


21 对象的转型
这一集特让我纠结!作者说的不是很详细,而且给出的结论也跟我自己做实验的不符。最最最重要的是,作者介绍了对象的转型却没有举个例子说明其有什么作用。让我感觉这玩意是不是没啥用的。。。
对象向上转型:将子类的对象赋值给父类的引用。
如:Student(子类)继承 Person(父类)
       Student   s = new Student();        // 创建一个子类对象 s指向这个对象
       Person    p = s;                           //通过子类的引用将Student对象赋值给父类的引用
       此时sp指向的是同一个对象。那么是否能把p当成s去使用呢?看下面的例子。
class Person
{
       String name;
       int age;
       String yiyang;

       // 父类有的
       void Person_fun()
       {
              System.out.println("父类:Person_fun执行");
       }

       void OutMsg()
       {
              System.out.println("父类:OutMsgyiyang = "+yiyang);
              System.out.println("父类:我的名字是" + name + "我的年龄是" + age);
       }
}
class Studentextends Person
{
       String address;
       String yiyang;               //和父类同名的
       void Student_fun()
       {
              System.out.println("子类:Student_fun 执行super.yiyang = " + super.yiyang);
       }

       void OutMsg()
       {
              super.OutMsg();                   // 调用父类的OutMsg函数               
              System.out.println("子类:我的地址是address=" +address + " yiyang=" + yiyang);      //这是子类新增加的代码
       }
}

class Test
{
       publicstatic void main(String[] args)
       {
              System.out.println("---------------邪恶的分割线-------------");
              System.out.println("以下是父类的对象操作。。。。");
              System.out.println("------------------------------------------");

              Person p1 = new Person();
              
              p1.yiyang = "父类yiyang";
              p1.name = " 父类";
              p1.age = 21;
              //p1.address = "广州";   // 由于Person类没有这个变量 当然编译报错

              p1.OutMsg();         //直接调用Person类的函数OutMsg();
              //p1.Student_fun(); // 由于Person类没有这个函数 当然编译报错
              p1.Person_fun();    //直接调用Person类的函数OutMsg();



              System.out.println("\n\n---------------邪恶的分割线-------------");
              System.out.println("以下是子类的对象操作。。。。");
              System.out.println("------------------------------------------\n");

              Student s1 = new Student();
              
              s1.yiyang = "子类yiyang";           // 与父类同名变量,赋值的是子类的变量
              s1.name = " 子类";                            // 子类没有。赋值的是父类的变量
              s1.age = 22;                                //同上
              s1.address = "深圳";                    // 父类没有,赋值的是子类的变量

              s1.OutMsg();                       //该函数被重写(覆盖)所以调用的是子类的函数
              s1.Student_fun();                 //子类独有,调用的是子类的
              s1.Person_fun();                  // 子类没有,调用的是父类的
              


              System.out.println("\n\n---------------邪恶的分割线-------------");
              System.out.println("以下是对象向上转型操作。。。。");
              System.out.println("------------------------------------------\n");

              Student s = new Student();
              Person  p = s;              // 对象的向上转型
              
              p.yiyang = "上转—yiyang";   // 与子类同名,实际上赋值的是父类的成员变量
              p.name = " 对象向上转型";  //只有父类有这个成员变量 赋值的是父类的成员变量
              p.age = 23;            //赋值的是父类的成员变量  赋值的是父类的成员变量
              //p.address = "广东";     // 在父类没有这个成员变量,编译会报错这行
              
              p.OutMsg();         // 被复写(覆盖)的函数,调用的是子类的OutMsg()               
              //p.Student_fun();   // 在父类没有这个成员函数,编译会报错这行
              p.Person_fun();     //可以调用父类的成员函数

       }     
}
java编译输出:

如果没有红色字体没有被注释则输出:
D:\MyJava>javacTest.java
Test.java:14: 错误: 找不到符号
                p1.address = "广州";    // 由于Person类没有这个变量 当然编译报错

                  ^
  符号:   变量 address
  位置: 类型为Person的变量 p1
Test.java:17: 错误: 找不到符号
                p1.Student_fun();       // 由于Person类没有这个函数 当然编译报错

                  ^
  符号:   方法 Student_fun()
  位置: 类型为Person的变量 p1
Test.java:49: 错误: 找不到符号
                p.address = "广东";     // 在父类没有这个成员变量,编译会报错这

                 ^
  符号:   变量 address
  位置: 类型为Person的变量 p
Test.java:52: 错误: 找不到符号
                p.Student_fun();        // 在父类没有这个成员函数,编译会报错这

                 ^
  符号:   方法 Student_fun()
  位置: 类型为Person的变量 p
4 个错误




如果注释了红色字体则成功被编译。输出的执行结果是:

D:\MyJava>java Test
--------------- 邪恶的分割线 -------------
以下是父类的对象操作。。。。
------------------------------------------
父类:OutMsgyiyang = 父类yiyang                // 这个就不用解释了,非常普通的类操作
父类:我的名字是 父类我的年龄是21
父类:Person_fun 执行


--------------- 邪恶的分割线 -------------
以下是子类的对象操作。。。。
------------------------------------------

父类:OutMsgyiyang = null        // 这里的yiyang是父类的,没给父类yiyang赋值自然是null
父类:我的名字是 子类我的年龄是22         //子类没有同名变量,所以是给父类赋值
子类:我的地址是address=深圳 yiyang=子类yiyang     
子类:Student_fun执行super.yiyang = null  //同名变量,赋值的是子类的,而不是父类的
父类:Person_fun 执行


--------------- 邪恶的分割线 -------------
以下是对象向上转型操作。。。。
------------------------------------------

父类:OutMsgyiyang = 上转—yiyang
父类:我的名字是 对象向上转型我的年龄是23
子类:我的地址是address=null  yiyang=null           //可以发现子类的变量并没有被赋值
父类:Person_fun 执行


我们可以总结一下,对象的向上转型,在访问变量和函数的时候,和直接操作父类对象相比,当父类对象调用不存在的函数和变量时,编译器直接报错。向上转型对象也是。唯一和直接操作父类对象不同的是,在调用被子类重写(覆盖)的函数时,向上转型对象操作的是子类的函数,而操作父类对象则是直接调用父类的函数。



下面是作者给出的结论:
       一个引用能够调用哪些成员(变量和函数),取决于这个引用的类型
       一个引用调用的是哪一个方法,取决于这个引用所指向的对象
(让我郁闷的是,函数和方法不是指一样东西么,很矛盾。而且第二个结论是有前提的,那就是那个方法(函数)要被子类重写过才成立.

下面我们看看对象的向下转型,由于视频并没有做过多介绍,所以唯有自己做实验。
向下转型 将父类的对象赋值给子类的引用
例:Student s1 =new Student();
       Personp = s1;
       Students2 = (Student)p;
或:Person p =new Student();
       Students2 = (Student)p;

Test.java文件中加入以下代码:

class Test
{
       publicstatic void main(String[] args)
       {
              //......
              //这代码和上面的一样,就不写出了。
              //......
              System.out.println("\n\n---------------邪恶的分割线-------------");
              System.out.println("以下是对象向下转型操作。。。。");
              System.out.println("------------------------------------------\n");

              Studentss = new Student();
              Personpx = ss;
              Studentsx = (Student)px;
                     
              sx.yiyang= "下转-yiyang";
              sx.name= "对象向下转型";
              sx.age= 25;
              sx.address= "惠州";
              
              sx.OutMsg();
              sx.Student_fun();
              sx.Person_fun();

       }     
}
看看输出的结果:



发现向下转型和直接使用子类没啥区别。。。擦......

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表