前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >A4第四章第2节null和成员变量、局部变量的不同初始化

A4第四章第2节null和成员变量、局部变量的不同初始化

作者头像
静心物语313
发布2020-03-24 11:15:10
5350
发布2020-03-24 11:15:10
举报
文章被收录于专栏:静心物语313的Coding

A4第四章第2节null和成员变量、局部变量的不同初始化第4节 1、null表示变量没有指向任何对象 如:Person p=null; p.sayHello();//结果会抛出异常 2、对于一个为【null的变量】调用【成员方法】都会报异常NullReferenceException。

3、值类型(ValueType):数值类型(int、long、double等)、boolean等基本类型,枚举、结构体。不能为null。String不是值类型。

public void setAge(int age)

{

this.age = age;

}

1、局部变量【必须初始化】,成员变量声明时【默认初始化】,基本数值类型【默认初始值为int】,String等非基本类型【初始化为null】。why?涉及到栈内存和堆内存,以后讲。

A4第四章第2节定义类字段方法及实例化类

第四章第2节 1、字段不加public,定义的方法加public 2、方法一般是大写开头

3、最简单的类:class Person{}

4、增加类变量(字段)(成员变量)和方法:

class Person{ private int age;//成员变量 private String name; public void setAge(int age1)//定义的方法setAge方法,age1为传入的变量 { this.age = age1; } public void setName(String name1)//定义setName方法,name1为传入的变量 { this.name = name1; } public void sayHello()//定义sayHello方法 { Console.WriteLine("大家好,我是"+name+",我今年"+age+"岁了"); } //再提供get方法 }

5、类的实例化: Person lzy = new Person();// lzy.setName("林志颖"); lzy.setAge(80); lzy.sayHello(); //两个对象的内存分配:根据模板拷贝两份。 yzk.sayHello(); new出的每个对象都是一个单独的实例,两个对象之间的成员变量是独立的两份。new出来的叫【类对象】或者【实例(Instance)】。 6、我们定义一个【类】后,就必须实例化才能使用。【实例化】就是创建一个【对象】的过程。 在C#中,我们使用new运算符关键字来创建。 7、 类 对象=new 类(); 即 class object=new class(); 即Person xcl=new Person(); 8、比如有一个类叫汽车。你现在想在程序中买一辆,所以你用new来买了一辆汽车,这辆车你得给它找个名字, 比如宝马。 例如:汽车 宝马 = new 汽车(); 你有钱了,你要再来一辆: 汽车 奔驰 = new 汽车();

A4第四章第5节this解决成员变量和局部变量重名的问题

第四章第5节 1、当成员变量和局部变量(函数参数也可以看做局部变量)重名的时候,被看做局部变量,因此为了避免混乱,建议访问成员变量的时候加上“this.”,this代表当前对象。

2、new Person().sayHello();创建一个匿名对象,然后调用。输出结果是? new Person().sayHello(); 等价于 Person t=new Person(); t.sayHello(); 3、【类】里边定义的变量是成员变量,【方法】里边定义变量叫做局部变量

A4第四章第6节public和private

第四章第6节 1、我们可以把age成员变量声明为public,也可以把setAge声明为private,这样就只能在【类内部】调用private成员(再写一个方法调用private的setAge)

2、结论:public成员可以【被类内部或者外部】访问,private成员【只能被类内部】访问。这样可以保护不希望外接调用的内部成员(Member,包含字段Field/变量、方法)不被外界访问。

3、直接通过public的age设置年龄,不通过setAge赋值,这样有什么坏处?-1。【不能有效控制非法字符的赋值】

4、字段(Field)/成员变量(Member Variable)一般声明为private。通过get/set方法来进行取值/赋值。

A4第四章第7节属性入门

第四章第7节 1、为了避免外界给成员变量随便赋值,必须把成员变量声明为private,然后提供get/set方法,写起来、调用起来都麻烦,C#提供了“属性”这样一个语法:

private int height;//成员变量 public int Height//写成大写格式,方便外界调用属性值//如果改为private则只能在内部调用 { get { return this.height; } set { this.height = value; } } p.Height=50;//相当于调用【set方法对p的Height进行【赋值】 int a = p.Height;//相当于调用【get方法对p的Height进行【取值】

通过Reflector看属性本质上是什么?( ILSpy的C#看的优化后的代码,IL看的是IL代码,看不懂 )

public void set_Height(int value)//反编译中查看的代码set { this.height = value; } public int get_Height()//反编译中查看的代码get { return this.height; }

A4第四章第8节 属性的简化写法

第四章第8节 1、//如果是简单地set。get逻辑,暂时没有更多的逻辑代代码,可以简化如下; public string Name { get; set; } 2、Reflector反编译器 查看PropertyTest1.exe--{}propertyTest1-Name:string 发现显示的语法其实还是以前讲的定义的 public void getAge(int Age) { return this.Age; } public void setAge(int Age) { this.Age=Age; }

1、如果是简单set/get逻辑,可以使用更简写的语法: public int Weight { get; set; } 通过Reflector看本质是什么

2、get、set可以有一个声明为private、protected,这样就可以设置不同的访问级别。

3、如果只有get或者set就是只读或只写属性。只读只写【不能简化写】。

A4第四章第9节 构造函数入门和属性赋值的简化写法

第四章第9节 1、构造函数是创建类对象,并且在创建完成前对类进行初始化的特殊函数。如果定义类时没有声明构造函数,【默认】会给出一个无参构造函数,如果定义了任意一个构造函数,将【不会】提供默认的无参构造函数。

2、构造方法/函数格式及特点:

方法名【必须】和类名一致

【没有】返回值类型

构造函数可以重载,Person(String name,int age)

3、 class Person { public int Id { get; set; }//id属性 public string Name { get; set; }//Name属性 public int Age { get; set; }//Age属性 public Person()//默认的构造函数【也可以不写,但是通过反编译器会看到它是默认存在的】 { } public Person(int id)//构造id函数,给id进行初始化、、它的存在会使默认的构造函数失去。除非。你申明了默认构造函数 { this.Id = id; } } Person p = new Person() { Id=5,Name="abc"};//new出来一个新的对象,并且赋值id和Name Person p1 = new Person(5) { Name = "aaa", Age = 12};//Person后的括号中的5其实是初始化年龄为5,花括号内的Age又重新对new出的对象赋值了12 Person p2 = new Person { Id=5,Name="a"};//Person后的括号可以省去,但是最好不要省去

通过ILSpy反编译看一下,还是一个编译器玩的“语法糖”,所以和构造函数不一样,赋值是在对象构造之后

A4第四章第10节static介绍

第四章第10节 1、一些场景下会要求一个类的多个实例共享一个成员变量;有时候想定义一些不和具体对象关联、不需要new就调用的方法

举例:Console类的WriteLine,MessageBox的Show

2、static方法不需要new就可以直接通过类名调用。

3、static变量不需要new就可以直接通过类名调用。static变量是共享的内存空间,非static变量则是对象隔离的。

4、static 方法中无法使用this关键字,因为static独立于对象存在,不是任何人的唯一。

5、static成员中只能访问static成员,不能直接访问非static成员。非static成员可以访问static成员。

A4第四章第11节单例模式

第四章第11节 1、有的类在系统中只能有一个对象(*,资源管理器、缓存管理器等),这时就要使用“单例模式”(singleton)。实现单例模式有很多方法,先介绍最简单、最实用的“饿汉式”。

2、单例模式的实现步骤:

1)构造函数声明为private,这样避免外界访问

2)定义一个private readonly static的对象实例,static成员的初始化只在类第一次使用的时候执行一次。readonly修饰变量只能在构造函数或者初始化的时候赋值。

3)定义一个public static的getInstance方法,返回唯一实例。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SingletonTest1 { class God { //静态变量的初始化只执行一次 private static God Instance = new God(); private God() { }//构造函数声明为private,避免外界调用 public void ZhaoYaoDaDi() { Console.WriteLine("照耀"); } public static God GetInstance() { return Instance; } } }

A4第四章第12节静态代码块以及面试题

第四章第12节 class MyTest { static MyTest() { Console.WriteLine("zi 静态代码块"); } public MyTest() { Console.WriteLine("zi 构造方法"); } } MyTest t1 = new MyTest(); MyTest t2 = new MyTest(); 【静态代码块在类第一次被使用的时候执行一次,在构造函数执行之前执行。【只要用到类】,哪怕没new对象(比如只是声明变量)也会被执行,且只执行一次。

public class MyJingTaiDaimaKuai { public static int i = test1();//最开始执行 public int age = test2();//new的时候先执行成员变量的初始化,再执行构造函数 static MyJingTaiDaimaKuai() { Console.WriteLine("静态代码块");//再执行 } public MyJingTaiDaimaKuai() { Console.WriteLine("构造函数"); } public static int test1() { Console.WriteLine("test1"); return 3; } public static int test2() { Console.WriteLine("test2"); return 333; } } MyJingTaiDaimaKuai a1 = new MyJingTaiDaimaKuai(); Console.WriteLine(a1.age); MyJingTaiDaimaKuai a2 = new MyJingTaiDaimaKuai(); Console.WriteLine(a2.age);

【一般用于对类进行初始化,以后会用

只要一旦开始“接触一个类”,静态成员、static代码块就会被执行】

A4第四章第13节命名空间

第四章第13节 用文件系统的文件夹解释避免文件名重复的问题。

命名空间语法:

namespace ConsoleApplication1包住类;

当前命名空间中的类无需引用;使用using引用其他包中的类:

还可以直接通过“命名空间+类名”的方式使用“System.Data.SqlClient.SqlConnection”,不用using,适用于同时使用多个重名的类,比using时候的别名好;

A4第四章第14节继承基本语法

第四章第14节 C#中一个类可以“继承”自其他类,如果A继承自B,则A叫做B的子类,B叫做A的父类(基类)。子类会从父类继承所有非private成员。子类还可以有子类。

C#中一个类只能有一个父类,如果没指定父类,则System.Object为父类。

class FuLei { private void method1() { } public void method2() { } } class ZiLei : FuLei { private void method3() { } public void method4() { } } ZiLei zl1 = new ZiLei(); zl1.method1(); zl1.method2(); zl1.method4(); zl1.toString();

A4第四章第15节继承中的构造函数

第四章第15节 C#中一个类可以“继承”自其他类,如果A继承自B,则A叫做B的子类,B叫做A的父类(基类)。子类会从父类继承所有非private成员。子类还可以有子类。

C#中一个类只能有一个父类,如果没指定父类,则System.Object为父类。

子类的构造方法默认都去访问了父类的【无参构造方法】:在子类中的构造方法后都有一行默认语句 base()

class Fu { public Fu() { Console.WriteLine("fu"); } } class Zi : Fu { public Zi() : base()//不管是否显式调用,控制台都会输出fu { Console.WriteLine("zi"); } } Zi z = new Zi(); 先执行父类的构造函数把父类初始化完成,再初始化子类的。

可以通过super(参数)去访问父类中的有参构造函数。可以通过this(参数...)去访问本类中的其他构造函数。

class Fu { public Fu(int a) { Console.WriteLine("fu"+a); } } class Zi : Fu { public Zi():base(0)//为了避免出错,给父类传递一个整数0,来调用父类的有参构造函数 { Console.WriteLine("zi"); } public Zi(int a):base(a)//默认会调用父类的无参的构造函数。不过父类中没有无参构造函数,故将a传递给父类的构造函数 public Fu(int a) { Console.WriteLine("zi"+a); } } 如果定义了构造函数,则类就不会有默认的无参构造函数;如果父类中没有默认的,则子类构造函数必须显示调用父类的构造函数

一个类如果没有定义其他构造函数,则有一个【默认的无参构造函数】。构造函数会默认调用父类的【无参构造函数】 子类的无参或者是有参构造函数都会默认调用父类的【无参构造函数】

A4第四章第16节 private、public和protected的区别

第四章第16节 private成员无法被子类访问,子类只能通过父类的非private方法“间接”访问父类的private成员。这样保证了父类private成员的安全性。

procected成员只能被自己以及子类(直接或者间接)访问,无法被“外姓人”访问。

A4第四章第17节 Override

第四章第17节 面向对象三大特征:封装、继承、多态。多态是面向对象最强大的一个特征,也是最难的一个特征,设计模式等都是多态的体现。大型项目架构也大量应用多态。

子类中定义和父类中一样的方法就叫“重写(Override)或覆盖”,父类中可以被Override方法要声明为virtual 。Override和OverLoad区别见备注

class DiQiuRen { public virtual void speak(){Console.WriteLine("我是地球人");} } class Chinese : DiQiuRen { public override void speak(){Console.WriteLine("我是中国人");} public void baiNian(){Console.WriteLine("过年好!");} } DiQiuRen dqr1 = new DiQiuRen(); dqr1.speak(); Chinese zgr1 = new Chinese(); zgr1.speak();

面试常考: OverLoad:重载,方法的名字一样,参数的类数的个数或者类型不一样。 OverRide:重写,子类有和父类一样(名字,参数个数,类型,返回值)的方法(非private)

A4第四章第18节 多态的精髓

第四章第18节 1、不能用【子类的变量】指向【父类的对象】 例如:Chinese zgr2=new DiQiuRen();//地球人不一定是中国人 2、可以用【父类的变量】指向【子类的对象】 例如:DiQiuRen dqr2=new Chinese();//中国人一定是地球人 3、调用方法还是对象的方法,而不是变量类型的实现 4、记住::【【能够调用什么方法由变量类型决定,执行谁的方法由实际指向的对象决定】】 DiQiuRen dqr1=new Chinese(); DiQiuRen 是变量类型,,Chinese是指向的对象

下面的执行结果是什么?? Chinese zgr2=new DiQiuRen();//地球人不一定是中国人 DiQiuRen dqr2=new Chinese();//中国人一定是地球人 dqr2.sayHello();//实际上执行的是Chinese里的sayHello而不是DiQiuRen里的sayHello方法。。执行谁的方法由实际指向的对象决定

5、变量类型是“把对象看成什么”,DiQiuRen dqr2=new Chinese()是把Chinese对象看成是“地球人”,因为“地球人”不一定有baiNian方法,因此dqr2.baiNian()编译失败。

A4第四章第19节 多态与类型转换

第四章第19节 1、编译器只看类型,无法看实际是什么对象 2、ZGR zgr2=(ZGR)dqr2//显示转换..父类显示转换为子类 3、

下面程序的执行结果是什么?

Chinese zgr5 = (Chinese)dqr2;

zgr5.sayHello();

zgr5.baiNian();

Chinese zgr5 = (Chinese)dqr1;

()类型转换可以把“被看做父类对象的实例”重新看成“子类”。(显式类型转换/强制类型转换)

如果对象就是父类对象,当被看成子类对象的时候会失败,抛出运行期异常,编译器无法发现这个错误。

类型转换只能在有父子关系的类中进行

思考:

1、定义一个方法 void test1(DiQiuRen dqr){dqr.sayHello();}

如下调用test1(new Chinese());可以吗?运行结果是什么?

2、String s = (String)zgr1;可以吗?

A4第四章第20节抽象类

第四章第20节 1、把类标记为abstract,这样的类无法被直接实例化(new),这就叫抽象类。

2、DiQiuRen的sayHello输出“我是地球人”显然不合理,因为无法确定怎么说,也就是DiQiuRen不知道如何sayHello, 只有具体到中国人、日本人、美国人才知道如何sayHello

3、把DiQiuRen的sayHello的方法体去掉,并且方法增加abstract修饰,类也修饰为abstract:

abstract class DiQiuRen

{

public abstract void speak();//没有方法体的抽象方法

}

4、抽象方法没有方法体;一旦类中定义了抽象方法,类必须被修饰为抽象;抽象类无法实例化(new)。 5、抽象类中不一定有抽象方法

A4第四章第21节接口

第四章第21节接口 1、接口是一种用来声明“能力”的类型,不提供具体实现

语法:

public interface ISpeakable

{

void speak();

}

2、不提供实现方法,连{}都不能有。

3、接口无法实例化,只能被类“实现”

public class TeacherCang : ISpeakable

{

}

4、既可以使用接口类型变量又可以使用类类型变量调用speak

5、接口的意义是定义“做什么”,类定义“怎么做”

6、接口中不能声明变量(字段),一个没有实现代码的接口中声明变量没意义。

7、接口中可以定义多个方法,也可以不定义任何方法(* 标识接口)。

8、接口只是“能力”不是“实现”,因此不能也没必要定义构造函数。

9、类只能有一个父类,类可以实现多个接口。测试一下:Speakable、Walkable。

************************************************************************************** 接口和抽象类的区别和联系(常见面试题,自己先看看)

1、抽象类里面可以有非抽象方法 但接口里只能有抽象方法 声明方法的存在而不去实现它的类被叫做抽像类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽像类,并让它指向具体子类的一个实例。不能有抽像构造函数或抽像静态方法。Abstract 类的子类为它们父类中的所有抽像方法提供实现,否则它们也是抽像类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。

2、接口(interface)是抽像类的变体。在接口中,所有方法都是抽像的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽像的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对像上调用接口的方法。由于有抽像类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档