拖欠的Java笔记

来源:互联网 发布:网络剧怎么赚钱 编辑:程序博客网 时间:2024/04/16 15:37

第二周学习笔记

几个小语法点

1.case穿透现象:
记住两个原则:switch结束条件要么是遇到break,要么是};一个switch只会判断一次case值。
假如执行完一个语句体没有break,就穿透到下一个语句体,没有再穿,直到break或者},这种穿透是无脑的,不判断case值的。
2.数组声明:
注意数组是引用类型,如果用等号复制只是复制了地址。
二维数组的声明方法有四种

int[][] a = new int[m][n];int a[][] = new int[m][n];int[] a[] = new int[m][n];int[][] a = new int[m][];Int[][] a = {{1, 2, 3}, {1, 2}, {4, 6}};

在JAVA中二维数组不是连续内存,存的是每行元素的起始位置指针。

用static和匿名对象提高内存使用效率

1.匿名对象:
就是直接通过类名访问调用,对某个类“一次性使用”的时候可用。
2.static关键字:
static把被修饰的成员或者方法变成静态的,共享的,所有该类对象共享这一份东西。静态的数据成员表征着所有对象的共性,比如说给中国人造一个类,全体中国人的国籍都是中国,那就可以存成静态的,这样即使创建了十三亿个对象,国籍这个数据也只有一份。
static修饰的东西都是随着类的加载而加载的,不等new一个对象出来就有了它们,所以说他们是“与对象无关”的,静态的数据成员和方法都可以通过类名直接调用。
那么注意了:首先,静态的代码块(就是在类中,方法外任意位置用花括号括起的块然后前面加上static)和成员方法一定是在构造方法之前执行的(常见一些判断输出结果的题目)。第二,静态函数不能用this关键字,也不能访问非static成员,因为这两个东西在static加载的时候还没出来。

public static void main(String[] args)

1.解释一下这几个关键字:
public 和 static两个修饰符被jvm识别,前者说明它大家(包括加载器啊,解释器啊各种部件)都可以访问它,后者说明它不依赖于对象,直接加载就能使用。
void也是告诉jvm这个主方法没有返回值。
main是一个通用的名字(但不是关键字),可以被jvm识别。
String[] args是从键盘接受的参数,它本身名义上是一个字符串数组,有地址且客观存在,但是没有元素,它是java语言发展早期的遗留产物。我们现在还可以在用cmd运行java程序的时候加进参数,比如这样的运行命令java Class Hello world,这时候arg就有值了,值是Hello world,可以被调用的。
2. 顺序:
前面说了静态的东西优先于对象的存在而存在,但它并没有比main更优先。而且并不是你写了什么类,加载器就会加载什么类的,main里面调用到什么才加载什么。静态的语句要执行也不会早于调用这个类的语句执行,也就是说,main里面有第一句话、第二句话、调用某个含静态方法或代码块的类A、调用某个含静态方法或代码块的类B……时,会按顺序执行第一句话、第二句话、A中静态的blabla,该调用语句,B中的静态blabla,该i调用语句……。
——宝宝我觉得在文档里面打代码好奇怪哦,想看真实效果?自己实验一下才是学习的正确打开方式嘛,略略略~~~

另,C++中在一个.c文件里面是允许在main外定义函数的,不需要先声明一个类在到类里面定;但java不同,java里凡事都需要依附类,赤果果地写一个函数,编译器都不认识这是什么于是就报错了

下面是我写的一个测试样例的部分
class test {    int a = 10;    static {        System.out.println("AAAAAAAA\n");    }} //Syntax error on token "}", delete this tokenstatic void hhh(int a) {    System.out.println(a);}public class AnimalDemo {    public static void main(String[] args) { //The method main cannot be declared static; static methods can only be declared in a static or top level type        test A = new test();        System.out.println(A.a);        Cat c = new Cat("mimi", 2);            Dog d = new Dog("wangwang", 3);            System.out.println(c.getN() +"---"+ c.getA());            test3 C = new test3();            System.out.println(d.getN() +"---"+ d.getA());            test2 B = new test2();            hhh(1);    }}class test2 {    static {//Cannot define static initializer in inner type AnimalDemo.test2        System.out.println("BBBBBBB\n");    }}class test3 {    static {//Cannot define static initializer in inner type AnimalDemo.test3        System.out.println("CCCCCCC\n");    }} //Syntax error, insert "}" to complete ClassBo        

报错的原因我也不是太理解,可能因为main只是一个通用的名字,假如这样写,编译器就以为hhh是主方法了,结果它什么也不会干,别的类都找不到加载的办法。欢迎批评指正

继承

1.概述:
     所有类都默认继承一个根类Object,它只有一个无参构造,每次系统为我们自动补上的构造方法都是调用它,知道为什么自动的是无参的了吧。java的继承规则中,只允许单继承和多层继承。(但接口允许多继承,完善了继承机制)
2.访问调用的特点:
   成员变量的调用采取就近原则(局部变量、子类数据成员、父类数据成员重名的时候),先在调用的局部范围内查找,然后是子类,然后是父类(非私有部分)。或者也可以用super和this明确指定用哪里的。
    成员方法调用方法类似,有重载时优先调用自己的版本,如果自己没有会向上找爸爸的、找爷爷的……
    构造方法,目前来讲,我不觉得构造方法和普通成员方法有什么本质上的区别。需要注意的是,我们写构造函数的选择有很多,可以不写,也可以写,写了的话还可以在里面调用父类的构造函数,这时我们就要清楚这些写法下分别发生了什么。假如不写,那么系统自动帮我们补上了一个,里面就是一句话——调用父类构造。如果写了但没写调用父类构造的话,那么系统还是帮我们加上了这句话!如果自己非常勤勉地显示调用了父类构造(需要对父类的数据成员传参初始化的时候这么干就是个不错的选择),即在开头写上super();(一定要是第一句话),那么问题来了,不是说在main里面创建子类对象的时候先自动调用父类构造吗,我这里自己又调用一遍那要执行两次吗?——当然不会啦,你这么勤勉,系统都不用帮你补全了呢!
2.构造方法私有化:
    即用private static修饰私有化成员。private使得不能人为创建它的对象,但可以直接通过类名调用其中的方法;static又保证一定有一个这样的类在加载的时候就被实例化出来。例如我需要一个纯粹的工具类里面写满了方法,没有数据成员啊。
   
另,在C++中也可以做类似的事,所不同的是没有通过类名访问方法这条规则,要调方法必须有对象。
    为了达到相似的目的,可以在”构造“函数中new一个对象然后返回他的指针(这样其实改变了它构造函数的本质了,就只是一个纯static函数)。或者通过友元访问。
    扩展一下,要设计一个产生限定个数对象的类的话,可以这样做:在class的私有域中添加一个static类型的计数器,它的初值置为0,然后再对那个静态中创建对象的函数做点手脚——每次调用它时先检查计数器的值是否已经达到对象个数的上限值,如果是则产生错误,否则才new出新的对象,同时将计数器的值增1。最后,为了避免复制时产生新的对象副本,除了将构造函数置为私有外,复制构造函数也要特别声明并置为私有。

3.static && 继承:
    继承中同时出现静态代码块、构造代码块、静态成员函数……执行顺序是怎样的呢?
    创建一个对象可以简单的看成两个过程:类的加载和对象的构造。加载的时候就要做完static的事情,而构造有三件事:先走构造代码块,再初始化已经显式指定值的成员变量(如果有的话),最后构造方法。所以,执行顺序是:父类静态代码块——子类静态代码块——父构造代码块——父构造方法——子构造代码块——子构造方法,加载过程先加载好父类才能加载好子类,构造过程先构造好父类的部分才能构造好自己的部分。

多态

1.概述:
    就是某一个事物在不同情境下根据需要表现出不同状态。比如我们看见猫,有时候描述它为猫,有时候描述它为小动物,描述成小动物的时候我们只需要看到它小动物的特性就好了。多态的前提是继承,表现是重写和父类引用指向子类对象,如动物 a = new 猫();。
2.final关键字:
    能保护被修饰的类、方法、成员不被重写和覆盖。修饰普通类型就使它变成自定义常量;修饰类这样的引用类型,它的保护作用则体现在变量的地址值上,即被修饰对象不可以改变地址值(类里面的成员要改还是可以的)。比如final Student s = new Student(); 再来一句s = new Student();——这是不可以的。
    注意:常量值只能赋一次,
在类构造完毕之前皆可。作为数据成员给了一次值就不要再在构造方法里面再给。
3.调用特点 && 向下转型:
    Father xiaoMing_fake = new Son(); 这种引用好似儿子装爹,穿上爹的衣服,粘上爹的胡子,但有些自己的行为还是可能会使他暴露身份。数据成员好比这个对象的“外型”,比如儿子打扮一番看起来有了爹的年纪——调用age数据成员,结果是爹的age;成员方法呢则是儿子自己的个性,比如小孩说话用的还是孩子的语言(重写已经覆盖掉了父亲的方法,当然了要是这个方法没有被重写,父子俩在这件事上表现一致,你说调用的是谁的版本都一样)——调用成员方法是自己的版本;而访问儿子特有的成员方式则是不允许的,儿子要装老子也得装的像啊,一玩游戏就会暴露的,所以不能玩——不允许调用子类特有方法。
    Son xiaoMing = (Son)xiaoming_fake; 向下转型时,儿子脱去了伪装,一切行为(调用)都以自己的版本和继承的规则为准。内存中,xiaoMing_fake也是保存了完整版的数据的,只是子类部分的不可见。

另,一个误区:

Animal a = new Dog();a = new Cat(); // 正确,把a指向的地址改成刚new出来的一个新的               //cat,而不是把那只狗变成猫。

抽象类

1.概述:
    有些概念性的东西只能是概念,而不能有实际的对象。动物就是一个纯粹的概念,任何一个动物都应该是它的子类的对象。这样的类被归为抽象类,可能含有抽象方法(没有方法体,只声明不定义),抽象类和抽象方法用abstract修饰。
    抽象类可以没有抽象方法(只是单纯不想实例化而已,但还是可以做事情的),可以有构造方法(自己不可以实例化,但子类或许可以,于是在构造方法里提供一个初始化自己数据成员的接口)。
2.abstract不能和哪些关键字共存:
    private——抽象的东西应该是完全的共性,private使得它不能被继承,违背了这一特性;final——抽象的东西需要被具体化,不能被重写违背了这一特性;static——加static使得方法能直接通过类名被调用,但抽象的方法只会说不会做,这样没有意义,而且还会报错。

接口

1.概述:
     设计理念上,继承对应“is a”,接口对应“like a“,它用来扩展类的功能和特性,允许多重继承——包括同时继承(我更喜欢说实现)多个接口和某个类、接口多继承接口。接口是用来干嘛的呢?知乎上给出了这样的解释:
知乎上的解释

2.接口的成员特点:
    数据成员默认为静态常量(最好自己冠上static),没有构造方法,成员方法成员默认abstract public(最好自己冠上)。

0 0