前言
在基本认识了一些基本数据类型后,开始学习引用类型,其中类和对象是Java学习中的重要内容,由于内容比较多,我可能记录比较乱,可能存在有些重要内容没有记录到的情况,因此后续可能会进行内容补充。
参考资料
1.《疯狂Java讲义》(第3版 李刚)P105-122
1. 类的新建与对象创建
示例代码如下,class关键字不能少
知识点1—当我们没有写构建器(或叫构造方法)时,系统会默认给一个无参的构造器,而当我们自己写了构造器时,系统默认给的无参的构造器就没了(那么这时如果我们还想使用这个无参的构造器,那么需要我们自己在类中写上)
如下图
编译并运行,如下图
修改Person类,如下
class Person{
int age;
float weight;
float height;
String name;
Person(String name){
this.name = name;
}
Person createPersonMethod1(){
return this;
}
void setName(String name){
this.name = name;
}
String getName(){
return this.name;
}
}
然后编译,报错如下
此时由于我们自己手动添加了构造器,因此系统默认给的那个无参构造器就没了,因此报错,若还想再使用那个无参的构造器,我们可以有两种处理方式:(1)在类中添加该无参构造器(2)将我们自己写入的构造器都删除,然后又是系统默认给我们添加那个无参的构造器。显然第一种解决方案更有优势,因此我们在类中添加该无参构造器,代码如下
class Person{
int age;
float weight;
float height;
String name;
Person(){
}
Person(String name){
this.name = name;
}
Person createPersonMethod1(){
return this;
}
void setName(String name){
this.name = name;
}
String getName(){
return this.name;
}
}
再次编译,没有错误,然后运行,结果如下
知识点2—还可以通过类中普通方法返回一个对象的方式创建对象
class Person{
int age;
float weight;
float height;
String name = "000";
Person(){
}
Person(String name){
this.name = name;
}
static Person createPersonMethod1(){
return this;
}
void setName(String name){
this.name = name;
}
String getName(){
return this.name;
}
}
编译,报错如下,这也是 知识点3—Java中类的静态方法不能直接访问非静态成员与方法
那么我修改如下呢?会怎么样
编译通过了
运行如下
这里我又好奇了,如果我不给类中的name赋初值"000",会怎么样呢?修改测试代码如下
编译运行结果如下
知识点3很重要,由该知识点我们也可以知道一个类中静态成员、静态方法、非静态成员、非静态方法之间的调用关系。
知识点4—方法连续调用
代码如下
class Person{
int age;
float weight;
float height;
String name;
int count = 0;
Person(){
}
Person(String name){
this.name = name;
}
static Person createPersonMethod1(){
return new Person();
}
void setName(String name){
this.name = name;
}
String getName(){
return this.name;
}
void getUp(){
System.out.println("Getting up...");
}
void brushTooth(){
System.out.println("Brushing tooth...");
}
void haveBreakfast(String food){
System.out.println("Having "+food+"...");
}
void addCount(){
count += 1;
}
void getCountResult(){
System.out.println("count = "+count);
}
}
编译,发现报错如下
根据李刚老师的书来修改代码,如下(将void都改为类名,然后这些方法都加入return this,当然前提是这些方法都是非static)
class Person{
int age;
float weight;
float height;
String name;
int count = 0;
Person(){
}
Person(String name){
this.name = name;
}
static Person createPersonMethod1(){
return new Person();
}
void setName(String name){
this.name = name;
}
String getName(){
return this.name;
}
Person getUp(){
System.out.println("Getting up...");
return this;
}
Person brushTooth(){
System.out.println("Brushing tooth...");
return this;
}
Person haveBreakfast(String food){
System.out.println("Having "+food+"...");
return this;
}
Person addCount(){
count += 1;
return this;
}
Person getCountResult(){
System.out.println("count = "+count);
return this;
}
}
编译,没有问题,然后运行,结果如下
当然,如上是不同方法连续调用,当然相同方法肯定也可以这样实现连续调用,Person类代码不变,修改MainActivity类中的代码,如下
编译,运行,结果如下
当然,这样写也没问题
编译,运行,结果如下
知识点–5-略(见总结)
知识点6—堆内存(heap)和栈内存(stack)
李刚老师的书讲得很详细,并且用图生动表达了,在我理解,就是真正的对象存在于堆内存中,每当我new一个,堆中就多出一个。
而对于栈内存区,暂且简单理解为每调用一个方法(包括入口的main方法)就对应开辟一个栈,然后该方法中的局部变量名就存在于该方法开辟的栈(当然现在只是简单理解,我这个表达可能非常不严谨、非常不正确)。
案例代码如下
编译、运行结果如下
如上结果,虽然有三个Person类型变量,但是实际上只new了两次,因此只有两个Person对象存在于堆中,p1和p3都是指向同一个对象,因此无论是通过p1操作对象还是通过p3操作对象,操作的实际上都是同一个对象,而p2不与p1(或p3)指向同一个对象,因此p1操作对象对p2指向的对象没有影响!
2. 方法
2.1 方法在Java中的所属性(地位)
1.方法不能独立定义,只能在类体中定义(在接口里的那个称为声明)
2.从逻辑意义上,方法要么属于类,要么属于该类的某个对象
3.永远不能独立执行方法,执行方法必须使用类或对象作为调用者(注意虽然我们可以看到一个类中普通非静态方法之间的互相调用,看上去直接用了方法名,但实际上都是this.非静态方法名(参数),只不过this省略了,而静态方法被普通非静态方法调用,实际上都是类名.静态方法名(参数), 当然从这里我们也可以类比推测出成员访问的实质)
2.2 形参个数可变的方法
案例代码如下,在以上Person类的基础上添加如下方法
static void testF1(int age, String ... Names){
System.out.println("age: "+"\t"+age);
for (String name: Names){
System.out.println("name: "+"\t"+name);
}
}
编译和运行结果如下
李刚老师提到,形参个数可变的参数本质就是一个数组参数
于是我思考如下图,再添加一个testF1方法,第一个参数是int型,然后第二个是String[]型,那么这样和之前的testF1应该是参数一样的吧,那这样应该会报错
编译(居然没有报错,好奇怪)
运行
修改代码
编译运行(之前的可能是我Person.java修改后忘了保存。。。抱歉)
李刚老师还提到,一个方法中最多只能包含一个个数可变的形参
于是我试了试,测试代码如下
Person.java
Main.java
编译果然出错,如下
然后我再试一下数组类型的,代码修改如下
编译出错
然后修改Main.java,如下
编译和运行如下
因此,对于含有可变个数的形参的方法,我在后续会尽量用数组形式传入!
2.3 方法的传值机制
暂且需要理解的就是李刚老师给的两个例程(暂且先这样)
2.4 方法重载
Java中允许一个类中定义多个同名方法,但需要形参列表不同,以此来区分(其实我们一个类中有好几种构造器,也可以视为方法重载,只不过这个方法比较特殊,是构造器而已)
注意返回值的类型不能用来区分!!!
2.5 方法递归
由于这部分比较难以理解,后续再作补充!
3. 总结
知识点1—当我们没有写构建器(或叫构造方法)时,系统会默认给一个无参的构造器,而当我们自己写了构造器时,系统默认给的无参的构造器就没了(那么这时如果我们还想使用这个无参的构造器,那么需要我们自己在类中写上)
知识点2—对象的创建(通过构造方法创建及需要注意的事项,通过普通静态方法的创建和普通非静态方法的创建)
知识点3—静态方法不能访问非静态成员与非静态方法(这个在后续类的继承中super的应用也会体现)
知识点4—类中方法的连续调用(这个在Android开发中经常可以见到,也比较重要)
知识点5
类中成员变量的定义语法格式如下
[修饰符] 类型 成员变量名 [= 默认值]
类中方法的语法格式如下
[修饰符] 方法返回值类型 方法名(形参列表){
//可执行语句
}
无论是成员变量或者是方法,其修饰符的约定如下
修饰符可以省略,也可以是public、protected、private、static、final、abstract。其中public、protected、private三个最多只能出现一个;abstract 和 final 最多只能出现一个;static视需求,可出现也可不出现
知识点6
关于方法的一些基础知识方法重载、可变参数个数的形参及具体调用案例、递归方法(后续补充)、方法的传值机制等