------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
day07 01-面向对象-构造函数-概述
1、构造函数特点:
(1) 函数名与类名相同
(2) 不用定义返回值类型
(3) 没有具体的返回值
2、构造函数:构建创造对象时调用的函数。作用: 可以给对象初始化。
day07 02-面向对象-构造函数-默认构造函数
1、创建对象都必须要通过构造函数初始化。
2、一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参构造函数。
如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了。如果要需要,那你自己再定义回来。如果自己定义了构造函数,一般都会再定义一个空参构造,防止用户使用出现问题。
day07 03-面向对象-构造函数-构造函数与一般函数的区别
1、一般函数和构造函数有什么区别呢?
答:构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化。
一般函数:对象创建后,需要函数功能时才调用。
构造函数:对象创建时,会调用,只调用一次。
一般函数:对象创建后,可以被调用多次。
2、代码示例
public static void main(String[] args) {
Person p=new Person();
p.Person();//不是一般烂,是烂透了。构造函数的作用就是初始化
p.speak();
p.speak();
}
3、除了初始化之外,你再用对象去调用构造函数,java会报错。
public class Demo {
int x=3;
public static void main(String[] args) {
Demo d=new Demo();
d.Demo();
}
报错:
Exception in thread"main" java.lang.Error: Unresolved compilation problem:
Themethod Demo() is undefined for the type Demo
at com.itheima.Demo.main(Demo.java:12)
day07 04-面向对象-构造函数-重载
1、什么时候定义构造函数?
答:在描述事物时,该事物一存在就具备的一些内容,这些内容都定义在构造函数中。比如人类的名字、性别。
2、代码示例:
public class Demo {
public static void main(String[] args) {
Person p=new Person();
p.speak();
}
}
class Person{
String name=null;
int age=0;
Person(){
name="baby";
age=1;
}
public void speak(){
System.out.println(name+"...."+age);
}
}
以及:
public class Demo {
public static void main(String[] args) {
Person p=new Person();
p.speak();
}
}
class Person{
public void speak(){
String name="baby";
int age=1;
System.out.println(name+"...."+age);
}
}
以上两者都可以在调用speak方法的时候实现同一结果:baby….1
有何不同?
第二个之后在调用speak方法的时候,这个对象才有姓名、年龄。如果让他做其他事情的时候,他就没有姓名、年龄。这样不合适。
day07 05-面向对象-构造函数-内存图解
1、分析以下一段代码的内存图解:
class Person{
String name=null;
int age=0;
Person(Stringn,int a){
name=n;
age=a;
}
}
Person p=new Person("小强",10);
p.speak();
先开辟一块堆内存。
调用构造函数,构造函数进栈。name=n age=a,他在栈中,无name与age,去堆里找。
构造方法遇到return,弹栈。这时main方法中的p才有了指向。这时Person p=new Person("小强",10);中等号右边的内容才算结束。结束之后p才有了指向。
3、即使你没有定义构造函数,在实例化对象时,构造函数也会进栈。初始化对象,必须会调用一个构造函数,他不进栈,你怎么初始化?!
day07 06-面向对象-构造函数-细节
1、
构造函数与setter方法有何区别?
答:两者不矛盾。一个用来初始化对象,一个用来做后期更改。就像一个人生下来叫“旺财”,后来改名字了,叫“旺旺”,这个就用setter方法改。不然,你每次都用构造方法,这不要投胎了么。
2、回答以下两个问题:
Person()
{……}
Public void speak()
{……}
(1) Person()中能调用speak()吗?
可以。
(2) speak()中能调用Person()吗?
不能!Person只用于初始化,只在new对象的时候调用一次。
4、Person(){……}
void Person(){……}//加了void之后,这个函数就不是构造函数了,但你也不能说他错。
5、写一般函数,第一个单词首字母小写,构造函数首字母大写(因为类名第一个单词首字母大写,与类名一致)
6、定义完有参构造后,无参构造自动消失,你需要的话自己再手动定义一个。
7、构造函数中有return语句吗?
答:有!return用来结束函数的,所有函数都有return,你不写他也有。所有函数全有return,return后面不跟任何东西的话,起结束函数的功能。
8、分析以下代码的运行结果:
public class Demo {
public static void main(String[] args) {
Person p=new Person();
p.Person();
}
}
class Person{
Person(){
System.out.println("构造");
}
void Person(){
System.out.println("普通");
}
}
运行结果:构造
普通
day07 07-面向对象-this关键字-使用场景1-&this原理图解
1、this到底代表啥?
this代表对象,代表哪个对象呢?
代表当前对象。
this就是所在函数,所属对象的引用。this是一个引用!
简单来说,哪个对象调用了this所在的函数,this就代表哪个对象。
2、this原理图解
public class Demo05 {
public static void main(String[] args) {
Person p=new Person("旺财");
p.speak();
}
}
class Person{
String name;
int age;
Person(String name){
this.name=name;
}
void speak(){
System.out.println("名字是:"+name+"年龄是:"+age);
}
}
个人觉得,this并不完全等于p。this先于p有指向。因为构造函数未完成时,p还没有指向,但是this可用。
都省略了this。其实this被隐含了,但是若像上面name=name;出现了歧义,Java不知道给谁加this了,或者要不要加this了。这时,就需要你手动加,来告诉java哪个是堆里成员变量,哪个是局部变量。
3、参数列表中的name是局部变量,this.name是通过this这个引用找到了对应堆内存中的成员变量name。
day07 08-面向对象-this关键字-使用场景2-以及细节
1、构造函数可以调用一般函数。一般函数不能调用构造函数。那么构造函数与构造函数之间如何访问呢?
2、
3、 图解
public class Demo05 {
public static void main(String[] args) {
Person p=new Person("旺财",20);
p.speak();
}
}
class Person{
String name;
int age;
Person(String name){
this.name=name;
}
Person(String name,int age){
this(name);
this.age=age;
}
void speak(){
System.out.println("名字是:"+name+"年龄是:"+age);
}
}
方法会先从自己的栈内存中找name,找不到再到堆中去找。若在自己的栈中找到了,出现了歧义,我加上一个this,让他强制去找堆中的成员变量。
4、 this的使用场景2:this也可以用于在构造函数中,调用其他构造函数。(构造调用构造时才用)
5、 注意①:这种情况,this只能定义在构造函数的第一行!因为初始化动作要先执行。
6、 解释注意①:
7、 注意②:this()调用防止死循环调用,要记得留一个出口。
不留出口,会导致程序停下来,因为栈内存溢出了。无穷无尽的进栈,无人出栈。
day07 09-面向对象-this关键字-应用
1、this经典应用:可用this判断是否是同龄人。判断两个对象是否相等。
2、该代码方法应该只有一个参数。我与张三比,我有compare这个功能,你再把我作为参数搞进去干啥。而应该是由我来调用这个方法,把你张三作为参数传进来。
3、代码:
public boolean compare(Person p){
return this.age==p.age;
}
day07 10-面向对象-static关键字-数据共享
1、static本身是一个关键字,也是一个修饰符。他可以修饰成员变量、成员函数、内部类。
2、示例:
class Person{
String name;
String country="CN";
public void show(){
System.out.println(country+";"+name);
}
}
public class Demo06 {
public static void main(String[] args) {
Person p=new Person();
p.name="小强";
p.show();
}
}
day07 11-面向对象-static关键字-特点
1、static修饰的内容,可被类名直接调用。
2、那我全静态不就好了,还省的写对象。这种思想对吗?
错误!你static name为小强。那所有的人类都得叫小强吗?明显不行!
3、 static的特点
①static是一个修饰符,用于修饰成员。(成员变量和成员方法)
②static修饰的成员被所有的对象所共享。
③static优先于对象存在,因为static的成员随着类的加载就已经存在了。
④static修饰的成员多了一种调用方式,就是可以直接被类名所调用。
⑤static修饰的数据是共享数据,对象中存储的是特有数据。
day07 12-面向对象-static关键字-成员变量和静态变量的区别
1、成员变量和静态变量的区别
①两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。类在,静态变量就一直在。
②调用方式不同
成员变量只能被对象调用。
静态变量可以被对象调用,也可以被类名调用。
③别名不同
成员变量也称为实例变量。
静态变量也称为类变量。
④数据存储位置不同
成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区中,所以也叫对象的共享数据。static所修饰的变量被多个对象所共享。
3、 代码示例:
public class TestDemo08 {
public static void main(String[] args) {
Person per1=new Person();
per1.talk();
per1.country="JP";
per1.talk();
Person per2=new Person();
per2.talk();
}
}
class Person{
int age=10;
static String country="CN";
void talk(){
System.out.println("age:"+age+"_country:"+country);
}
}
运行结果:
age:10_country:CN
age:10_country:JP
age:10_country:JP
虽然只是per1将country从CN改成了JP,但由于country是共享数据,per2打印出来的也是JP。
day07 13-面向对象-static关键字-注意事项
1、静态使用的注意事项(静态的使用,绝对不牵涉到事先要有对象,不牵涉到堆内存,也就不牵涉到this、super这些引用指向)
①静态方法只能访问静态成员(非静态既可以访问静态,又可以访问非静态)。这成员包含两部分,一个是变量,一个是函数。
因为静态不用对象,而非静态成员在对象的创建时才会出现。
②静态方法中不可以使用this或者super关键字。
this、super可以调用构造函数,所以不行。this代表对象的堆内存地址。
③主函数是静态的。
2、代码示例
3、代码示例
public class TestDemo09 {
public static void main(String[] args) {
Person.talk();
}
}
class Person{
int age=10;
static String country="CN";
static void talk(){
Person per=new Person();
System.out.println("age:"+per.age+"_country:"+country);
}
}
运行结果:age:10_country:CN
静态方法talk(),通过对象调用非静态变量age完全没有问题(主方法其实也类似)。
4、代码示例
public static void main(String[] args) {
int x=0;
System.out.println(x);
}
ok。与静态方法只能调用静态变量不矛盾。这里说的调用,你在内部定义,再用它不算调用。在静态方法中new对象去调用也没关系。
day07 14-面向对象-static关键字-main函数解析
1、public static void main(String[]args)
2、主函数的特别之处:①、格式是固定的②、被jvm所识别和调用。
3、public:因为全县必须是最大的
4、static:不需要对象的,直接用主函数所属类名调用即可。
5、void:主函数没有具体的返回值
6、String[] args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型。
7、args只是一个名字
public static void main(String[] x)都OK。
8、public static void main(String[]args)
public static void main(String[] x)
挂了,到底哪个是入口?JVM无法分清。
9、
public static void main(String[] args) {
int x=0;
System.out.println(x);
}
public static void main(int x) {
int z=1;
System.out.println(z);
}
运行结果:0
可见,虽然有重载,但是java仍然从main(String args[])处开始。
day07 15-面向对象-static关键字-内存图解
1、代码示例
class Person{
private String name;
private int age;
static String country="CN";
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void show(){
System.out.println(Person.country+";"+this.name+";"+this.age);
}
public static void method(){
System.out.println(Person.country);
}
}
public class TestDemo11 {
public static void main(String[] args) {
Person.method();
Person p=new Person("java",20);
p.show();
}
}
2、
全部搞完后,main方法最后有return,main方法弹栈。
3、代码示例:
public class TestDemo12 {
public static void main(String[] args) {
Person per=new Person();
per.talk();
Dog d=new Dog();
d.talk();
}
}
class Person{
static String name="人";
public void talk(){
System.out.println(name);
}
}
class Dog{
static String name="狗";
public void talk(){
System.out.println(name);
}
}
运行结果:人
狗
Person类中定义的static变量只对这个类的对象有用。static变量是被给雷的对象来共享的。
day07 16-面向对象-static关键字-什么时候用
1、静态(static)什么时候用?
①静态变量
(不加静态在堆内存的对象中,加了静态在方法区中。不加静态,对象特有;加了静态,对象共有)静态变量放置内存浪费,不用在每个对象中都去定义,我只定义一个,归这个类所有的对象共有。
当分析对象中所具备的的成员变量的值都是相同的。这时这个成员就可以被静态修饰(对象特有跟对象共有的区别)。
只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中。(你要是全静态,就意味着不是共性的数据,也被共性了)定义成静态的。
②静态函数
(我对外提供的函数,到底是静态的呢,还是非静态的呢?)看他调用的数据类型。
函数是否用静态修饰,就参考一点,就是该函数功能是否有访问到对象中的特有数据。
简单点说。从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态的。
但是非静态需要被对象调用,而仅创建对象调用非静态的,没有访问特有数据的方法,该对象的创建是没有意义的。(非静态不需要对象,直接用类名调用即可)
day07 17-面向对象-static关键字-静态代码块
1、static{……}直接写在类中。
2、静态代码块,随着类的加载而执行,类只要一加载,就执行这个代码块。
3、静态代码块的作用:用于给类初始化。
有些类,是没必要创建对象的。例如类中成员皆静态,我创建这个类的对象就没意义了。那我不创建对象,就不能调用构造函数,那我咋初始化。答:用静态块给类初始化。但这种初始化方式用的不多。
4、如果静态块写到了主类中呢?
public class TestDemo13 {
static{
System.out.println("a");
}
public static void main(String[] args) {
System.out.println("b");
}
}
运行结果:a
b
可见,这里仍然先执行静态块,之后再执行主方法。主类一旦被创建,静态块就没执行了。
day07 18-面向对象-构造代码块
1、直接定义在类里面的代码块——构造代码块
2、构造代码块的作用:给该类的所有对象初始化。某部分相同的初始状态,但后期对象仍可以修改成自己各自独特的属性。
3、构造函数是给对应的对象进行针对性的初始化。