08 方法

本章主要讲了 名字是方法,却主要讲了构造器

实例构造器,静态构造器,在结构和类中的区别

生成了一样的代码,就算你不写构造器,编译器也默认生成一个

1     public class ClassTest
2     {
3         public ClassTest()
4             : base()
5         {
6
7         }
8     }
public class ClassTest
{ 

}
1   // 代码大小       7 (0x7)
2   .maxstack  8
3   IL_0000:  ldarg.0
4   IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
5   IL_0006:  ret

调用顺序.

 1     public class ClassTest
 2     {
 3
 4         public int a;
 5         public int b = 5;
 6
 7         public ClassTest()
 8             : base()
 9         {
10             a = 2;
11             b = 4;
12         }
13     }
  // 代码大小       28 (0x1c)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.5
  IL_0002:  stfld      int32 EFTest.ClassTest::b
  IL_0007:  ldarg.0
  IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
  IL_000d:  ldarg.0
  IL_000e:  ldc.i4.2
  IL_000f:  stfld      int32 EFTest.ClassTest::a
  IL_0014:  ldarg.0
  IL_0015:  ldc.i4.4
  IL_0016:  stfld      int32 EFTest.ClassTest::b
  IL_001b:  ret

先赋值.

然后在实例构造. 然后再赋值.

如果不没赋值,编译器会赋默认值,引用类型 NULL,值类型0.

值类型构造器

首先结构不允许 参数为空的构造器。编译器也不会创建默认构造器

1     public struct ClassTest1
2     {      //错误 1 结构不能包含显式的无参数构造函数 
3         public ClassTest1()
4         {
5
6         }
7     }

在没有显示声明的构造器的情况下也编译器也不会声明

1     public struct ClassTest1
2     {
3
4     }

调用的顺序和 CLass一样 。同样没有初始化 总是被初始化为0或null

结构不允许默认构造函数。

结构中不能有实例字段初始值设定项.

1 private Int32 m_x = 5;

包括构造函数必须所有参数都赋值,不能部分赋值

 1     public struct ClassTest1
 2     {
 3         private Int32 m_x ;
 4         private Int32 m_y ;
 5
 6         public ClassTest1(int x)
 7         {
 8             m_x = x;
 9         }
10     }

错误 1 在控制返回到调用方之前,字段“EFTest.ClassTest1.m_y”必须完全赋值

这些让我没有明白.

书中的说法是 "生成可验证的代码" 完全没有明白. 毕竟你完全可以这样

1     public struct ClassTest1
2     {
3         private Int32 m_x ;
4         private Int32 m_y ;
5     }
6
7 var o = new ClassTest1();
8 Console.WriteLine(o.m_x);

然后输出为 0 这不也赋值了吗? 为什么就不能不分赋值.

不允许无参构造和内联赋值.也不是特别明白.

这种不知道的感觉特别蛋疼

静态构造器

首先静态构造器相当于一个私有且无参的实例构造

 1     struct ClassTest1
 2     {
 3         Int32 m_x ;
 4         Int32 m_y ;
 5
 6         static ClassTest1()
 7         {
 8
 9         }
10     }
 1     public class ClassTest2
 2     {
 3         public static int staticcount = 0;
 4         public static int count = 0;
 5         static ClassTest2()
 6         {
 7             staticcount++;
 8             Console.WriteLine(" 静态构造调用 " + staticcount + "次");
 9         }
10
11         public ClassTest2()
12         {
13             count++;
14             Console.WriteLine(" 构造调用 " + count + "次");
15         }
16     }
1 var o = new ClassTest2();
2 var o1 = new ClassTest2();
3 var o2 = new ClassTest2();
4 Console.WriteLine(o1.GetType());
5 Console.WriteLine(o2.GetType());
6 Console.WriteLine(o2.GetType());

静态构造只调用了一次,而普通构造函数却能够每次初始化都调用.

上图也说明了调用顺序问题

此外,静态构造函数也只是由 CLR调用. 开发人员是无法调用的

关于性能损耗.

 1     public sealed class TypeConstructorPerformance
 2     {
 3         public static void Go()
 4         {
 5             const Int32 iterations = 1000 * 1000 * 1000;
 6             PerfTest1(iterations);
 7             PerfTest2(iterations);
 8         }
 9
10         internal sealed class BeforeFieldInit
11         {
12             public static Int32 s_x = 123;
13         }
14
15         internal sealed class Precise
16         {
17             public static Int32 s_x;
18             static Precise() { s_x = 123; }
19         }
20
21         private static void PerfTest1(Int32 iterations)
22         {
23             Stopwatch sw = Stopwatch.StartNew();
24             for (Int32 x = 0; x < iterations; x++)
25             {
26                 BeforeFieldInit.s_x = 1;
27             }
28             Console.WriteLine("PerfTest1: {0} BeforeFieldInit", sw.Elapsed);
29
30             sw = Stopwatch.StartNew();
31             for (Int32 x = 0; x < iterations; x++)
32             {
33                 Precise.s_x = 1;
34             }
35             Console.WriteLine("PerfTest1: {0} Precise", sw.Elapsed);
36         }
37
38         private static void PerfTest2(Int32 iterations)
39         {
40             Stopwatch sw = Stopwatch.StartNew();
41             for (Int32 x = 0; x < iterations; x++)
42             {
43                 BeforeFieldInit.s_x = 1;
44             }
45             Console.WriteLine("PerfTest2: {0} BeforeFieldInit", sw.Elapsed);
46
47             sw = Stopwatch.StartNew();
48             for (Int32 x = 0; x < iterations; x++)
49             {
50                 Precise.s_x = 1;
51             }
52             Console.WriteLine("PerfTest2: {0} Precise", sw.Elapsed);
53         }
54     }

这是书中一个例子

同样的例子 我和书中得出的结果是不一样的. 不知道是不是CPU进化的结果导致的.

直接内联构造和静态构造 性能还是有些差别的。

不过这种调用次数这种差别。 我觉得可以忽略了...

接下来就是一些操作符以及自己写语法糖的介绍, 比较简单,贴一下代码就可以了

操作符重载

 1  internal sealed class Complex
 2     {
 3         public Int32 a;
 4
 5         public Complex(Int32 c)
 6         {
 7             a = c;
 8         }
 9
10         public static Complex operator%(Complex c1,Complex c2)
11         {
12             var c3 = new Complex(c1.a + c2.a);
13
14             return c3;
15         }
16     }
 1 .method public hidebysig specialname static
 2         class EFTest.Complex  op_Modulus(class EFTest.Complex c1,
 3                                          class EFTest.Complex c2) cil managed
 4 {
 5   // 代码大小       21 (0x15)
 6   .maxstack  2
 7   .locals init ([0] class EFTest.Complex c3)
 8   IL_0000:  ldarg.0
 9   IL_0001:  ldfld      int32 EFTest.Complex::a
10   IL_0006:  ldarg.1
11   IL_0007:  ldfld      int32 EFTest.Complex::a
12   IL_000c:  add
13   IL_000d:  newobj     instance void EFTest.Complex::.ctor(int32)
14   IL_0012:  stloc.0
15   IL_0013:  ldloc.0
16   IL_0014:  ret
17 } // end of method Complex::op_Modulus
1 var c1 = new Complex(1);
2 var c2 = new Complex(2);
3 Console.WriteLine((c1 % c2).a);
 IL_0000:  ldc.i4.1
  IL_0001:  newobj     instance void EFTest.Complex::.ctor(int32)
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.2
  IL_0008:  newobj     instance void EFTest.Complex::.ctor(int32)
  IL_000d:  stloc.1
  IL_000e:  ldloc.0
  IL_000f:  ldloc.1
  IL_0010:  call       class EFTest.Complex EFTest.Complex::op_Modulus(class EFTest.Complex,
                                                                       class EFTest.Complex)

具体有哪些操作.

转换操作符方法

 1     public sealed class Rational
 2     {
 3         public Rational(Int32 num)
 4         {
 5             Console.WriteLine(num);
 6         }
 7
 8         public static implicit operator Rational(Int32 num)
 9         {
10             return new Rational(num);
11         }
12     }
Rational r1 = 1;

当然他也有反过来的操作 explicit.

扩展方法

 1     public static class StringExtensions
 2     {
 3         public static Int32 ToFuck(this String c)
 4         {
 5             if (c == null)
 6                 return -1;
 7
 8             return c.Length * 15;
 9         }
10     }

有点儿像 js 中更改原形一样.

默认返回一个自身.

以上这些方法都是让你语法更加简洁。

理论上不用这些都是可以用其他方法弄出来。

end

时间: 2024-10-08 20:14:53

08 方法的相关文章

08方法的实用与递归

方法(函数) 什么是方法 java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,. [修饰符1 修饰符2...]返回值类型 方法名(形式参数列表){ 程序代码; return 返回值; } 方法2中参数: 形式参数(形参):在方法被调用时用于接收外界输入的数据 实际参数(实参):调用方法时实际传给方法的数据 在一个类里,方法名相同时 参数列表必须不同(方法的重载)

JVM-class文件完全解析-方法表集合

方法表集合 前面的魔数,次版本号,主板本号,常量池入口,常量池,访问标志,类索引,父类索引,接口索引集合,字段表集合,那么再接下来就是方法表了.   方法表的构造如同字段表一样,依次包括了访问标志(access_flags),名称索引(name_index),描述符索引(descriptor_index),属性表集合(attributes)几项. 方法表结构: 类型 名称 数量 u2 access_flags 1 u2 name_index 1 u2 descriptor_index 1 u2

JavaSE_ Java基础 总目录(1~6)

黑马程序员_JavaSE学习总结第01天_Java概述01.01 计算机概述01.02 计算机硬件和软件概述01.03 软件开发和计算机语言概述01.04 人机交互01.05 键盘功能键和快捷键01.06 如何打开DOS控制台01.07 常见的DOS命令讲解01.08 扩展的DOS命令01.09 Java语言概述01.10 Java语言跨平台原理01.11 JDK和JRE的概述01.12 JDK的下载01.13 JDK的安装01.14 JDK的卸载01.15 Java开发工具介绍01.16 第一

linux一周学习总结

对于linux,之前也完全没有接触过,完全零基础小白.来到马哥以后,进入学习也有一周时间 ,一周里老师带我们学习了很多指令,下面,我就自己的理解和老师讲授的内容对linux中的一些指令做一个简单的小总结. ? 一.关于SHELL Shell 查询当前系统使用了哪个shell echo $SHELL 查询当前系统已安装的所有shell cat /etc/shells Shell提示符 whoami 显示当前的登录用户名 hostname 显示当前的主机名 pwd 显示当前的工作目录. 当然,这里面

JavaSE学习总结第05天_Java语言基础1

05.01 方法概述和格式说明 简单的说:方法就是完成特定功能的代码块 在很多语言里面都有函数的定义,函数在Java中被称为方法 格式: 修饰符返回值类型方法名(参数类型参数名1,参数类型参数名2...) {    函数体;    return 返回值; }   方法格式解释: 修饰符:后面会详细介绍.目前public static 返回值类型:用于限定返回值的数据类型 方法名:一个名称,方便我们调用方法 参数类型:限定调用方法时传入参数的数据类型 参数名:是一个变量,接收调用方法时传入的参数

JavaScript初探一

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <style type="text/css"&

Java学习之面向对象二

###01继承的概述 *A:继承的概念 *a:继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系 *b:在Java中,类的继承是指在一个现有类的基础上去构建一个新的类, 构建出来的新类被称作子类,现有类被称作父类 *B:继承关系的子类特点 *a:子类会自动拥有父类所有非private修饰的属性和方法 ###02继承的定义格式和使用 *A:继承的格式 class 子类 extends 父类 {} *B:雇员(Employee)与研发部员工(Developer)案例: *cn

class结构

结构如下: magic: class:文件的特定前缀,值为CAFEBABE minor_version:小版本号 major_version:大版本号 constant_pool_count:常量池数量 constant_pool:常量池中的各种值 access_flags:class:访问标志 如 priviate public static 等 this_class:类索引(在常量池中的索引) super_class:父类索引(常量池)无父类的class的父类是Object interfac

百度哈斯发卡号是减肥哈卡斯加分了卡斯

http://www.ebay.com/cln/ta_ya20/-/167521224015/2015.02.08 http://www.ebay.com/cln/p-m6466/-/167398283011/2015.02.08 http://www.ebay.com/cln/ta_ya20/-/167521242015/2015.02.08 http://www.ebay.com/cln/p-m6466/-/167398294011/2015.02.08 http://www.ebay.co