1. byte a = ‘a’; byte b = -127; byte c = “ab” ; byte e =256; 这些变量哪些是正确?哪些是错误的?错误的原因是什么?
首先要知道 byte 在 C# 的范围是 0~255。所以变量 b 和 e 是错误。
变量 c 是错误的,字符串类型没办法转成 byte 类型。
变量 a 是无法将 char 隐式转换为 byte,正确定义加一个 byte a = (byte) ‘a’; char a 会转为对应ASCII码97。
比如说下面代码是没问题的
byte a=2; char b='a'; Console.WriteLine(a+z); //输出 99
2. byte a = 255; a +=5; a 的值是多少?
byte 的取值范围是 0~255 ;a += 5 会溢出,结果为 4 。首先将 255 转化二进制为 ,5 的二进制为 101,然后根据加法运算如下:
3. int? 和 int 有什么区别?
int? 为可空类型,等同于 Nullable
表示其基础值类型正常范围值内,再增加一个 null 值,属于引用类型。它的默认值为 null。
int 默认为0,属于值类型。
4. 写个方法判断一个整数是否2的N次方。
- 取模,用num % 2 == 0 可以判断。
- 位运算逻辑并,运算的逻辑是通过二进制,都是 1 时才为 1,其余都 0,然后结果是否等于 0,代码如下
bool IsPower(int num) { int result = num & 2; return result == 0; }
5. 求一个整数是2的几次方?
int Seq(int num) { int n = 1; while (num / 2 != 1) { num = num / 2; n += 1; } return n; }
6. short s = 1; s = s+1; 和 short s = 1; s += 1; 哪个是正确,哪个错误?为什么?
s = s + 1; 先进行右边运算,1 默认是 int,s + 1 的返回值是 int , 然后再将右边得出的结果赋值给 s ,这时是不能将 int 类型隐式转换为 short 类型的。所以要加一个强制转换 s = (short)(s + 1) 。
而 s += 1;等价于 s = (short)(s + 1) ,它做了数据类型的转型,所以编译成功。
7. 如下代码,求 n 的值?
public class Class1 { public static int n = 0; static Class1() { n++; } public Class1() { n++; } }
Console.WriteLine("{0}", Class1.n); //1 Class1 class1 = new Class1(); Console.WriteLine("{0}",Class1.n); //2
静态构造方法只会调用一次,而实例化几次就会运行几次。
class A { public static int x; static A() { x = Program.y + 1; } } class Program { public static int y = A.x + 1; static Program() { } static void Main(string[] args) { Console.WriteLine("x={0},y={1}", A.x, y); //输出 x=1,y=2 Console.Read(); } }
8. 下面代码输出的结果是多少?
Console.WriteLine(Math.Round(11.5)); //12 Console.WriteLine(Math.Round(11.2)); //11 Console.WriteLine(Math.Round(11.7)); //12 Console.WriteLine(Math.Round(-11.5)); //-12 Console.WriteLine(Math.Round(-11.2)); //-11 Console.WriteLine(Math.Round(-11.7)); //-12
9. i++ 和 ++i 有什么区别。
i++ 是先赋值,再自增;++i 是先自增,再赋值。
10. 如何用最有效且快速的计算出2乘以8等于多少
使用位运算左移(<<)比较快,但这还要加一个前提乘数必须是 2 的次方,这样才能成立。解题的过程是将 2 转化为二进制 0000 0000 0000 0010 ,然后左移 1 位 0000 0000 0000 0100 转化成十进制就是 4;左移的位数刚好是乘数的次方。8 刚好是 2 的 3 次方,所以 2 乘以 8 相当于 2<<3。
11. 什么是装箱和拆箱
装箱就是隐藏地将一个值 类型转换成引用类型,如:
int i = 1; object o = i;
拆箱就是将引用类型转换成值类型,如:
int i = 1; object o = i; int n = (int)o;
12.值类型和引用类型的区别
- 分配不同
值类型存储在栈中,引⽤类型存储在堆中
- 释放方式不同
值类型在作用域内结时,会被系统自动释放,可心减少托管堆的压力;引用类型则靠GC,所以在性能上值类型优势比较明显。
- 继承不同
引用类型继承Object,且也可以被其它类继承。值类型不能作为基类,但是可以继承或者多继承接口。另外,值类型是继承ValueType,而引用类型不会继承ValueType。
- 传参方式不一样
值类型在传参的时候是复制内存的数据,而引用类型通过它们的引用来查找的,所以传参是共享一个内存地址。
- 初始化行为不同
引用类型需要通过 new 来创建对象。
其它,可以自行补充,至少回答3点吧。
13.new关键字的作⽤?
运算符:创建对象实例
修饰符:隐藏掉基类⽅法
public class Class1 { public void Add() { Console.WriteLine("Hello world!"); } } public class Class2 : Class1 { public new void Add() { Console.WriteLine("Hello C#!"); } }
约束:可以约束泛型类型,如:
public class Repository
where T : class, new() { }
使用 Repository
的时候 T 的类型必须类且有空构造函数
14.using关键字的作⽤
- 引用命名空间;为命名空间或类型创建别名。
- 释放资源,实现了IDisposiable的类在using中创建,using结束后会⾃定调⽤该对象的Dispose⽅法, 释放资源。
15. const 和 readonly 的区别
- const 不能用 static 修饰,只能通过类来访问;readonly 由实例对象来访问,可以用 static 来修饰。
- const 只能定义为值类型和 string 类型,readonly 没有限制类型。
- const 必须初始化值,在编译时会进行解析,readonly 可以在声明时和构造函数中进行初始化,不同的构造函数可以实现不同的初始值。
- const 可以定义为字段和局部变量,readonly 则只能定义字段
16.字符串中string str=null和string str=””和string str=string.Empty的区别?
这些的区别在于初始化对象内存分配上,str=null 还未分配内存空间,str=”” 和 str=string.Empty 分配了内存空间,且初始值都是””; Empty 是 static readonly 修饰的字段。
string str = string.Empty; string str1 = ""; string str2 = null; Console.WriteLine(ReferenceEquals(str, str1));//True Console.WriteLine(ReferenceEquals(str, str2));//False Console.WriteLine(ReferenceEquals(str1, str2));//False
可以通过”即时”面板查看内存分配情况:
17.什么是委托,主要用在哪里?
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。~摘自百度百科~
主要用于事件和函数回调。
18.什么是强类型,什么是弱类型?
强类型是在编译的时候就要确定数据类型,在执行的时候不能更改;而弱类型是在运行的时候才能确定数据类型。两者没有好坏,强类型在编译的时候确认数据类型安全性相对高一些,而且效率高。
19. ref 和 out 的区别
- ref 传参时,传入的参数必须先被初始化;out 不必
int i; Foo(ref i);//错误 Foo(out i);//通过
- ref 传进去的参数在函数内部可以直接使用,而 out 不可以
public void Foo(ref int i) { int n=i;//通过,因为 i 已经初始化值 }
public void Foo(out int i) { int n=i;//错误,已初始化不可直接使用 }
- ref 传进去的参数在函数内部可以不被改变,但 out 必须在函数体结束前进行赋值。
public void Foo(ref int i) { Console.WrilteLine(i);//通过 }
public void Foo(out int i) { i = 10; //这里必须赋值,不然会报未赋值 Console.WriteLine(i); }
20.Equals 和 == 的区别
对于值类型,两者比较的是变量的值
int n = 5; int m = 5; Console.WriteLine("n == m :{0}", n == m); //True Console.WriteLine("n.Equals(m) :{0}", n.Equals(m)); //True
对于引用类型,如果重写了 == 操作符,则比较的值,或者比较的是引用地址,看两段代码
string str = "Hello C#!"; string str1 = "Hello C#!"; Console.WriteLine("str == str1 :{0}", str == str1); //True Console.WriteLine("str.Equals(str1) :{0}", str.Equals(str1)); //True
可以知道 string 的 == 与 Equals 返回都是 True ,通过反编译的工具找到到代码如下:
public static bool operator ==(String? a, String? b) { return a.Equals(b); }
再看另外一段代码
public class Student { public int Id { get; set; } public string Name { get; set; } public Student(int id, string name) { Id = id; Name = name; } } Student stu = new Student(10086,"程序员"); Student stu0 = new Student(10086,"程序员"); Console.WriteLine("stu == stu0 :{0}", stu == stu0); //False Console.WriteLine("stu.Equals(stu0) :{0}", stu.Equals(stu0)); //False
另外,两个对像值相同(x.Equals(y)==true),其HashCode也是相同的。
21. as 和 is 的区别
as 在转换的同时判断兼容性,如果无法转换返回 null ,as 转换是否成功判断的依据是结果是否为 null
is 只是做类型兼容性的判断,并不执行真正的类型转换,返回 true 或 false
效率上 as 比 is 更高,as 只做一次类型兼容检查
22. 静态成员和非静态成员的区别
- 静态变量使用
static修饰符进行声明,不带有static声明的变量为非静态变量 - 静态变量在类被实例化时创建,通过类进行访问;非静态变量在对象被实例化时创建,通过对象进行访问
- 静态函数的实现里不能使用非静态成员,包含非静态变量和非静态函数;但非静态函数可以使用静态成员
23. struct 和 class 的区别
- struct 是值类型;class 是引用类型
- 不能声明无参数构造函数。每个 struct类型已经提供了一个隐式的无参构造函数,该构造函数会对声明的字段或属性进行设置默认值。从 C# 10 开始可以声明无参数构造函数 。
- 不能对实例字段或属性时进行初始化。但可以在声明中初始化静态或常量字段或静态属性。从 C# 10 开始可以对实例字段或属性进行初始化。
- struct 类型的构造函数必须对所有实例字段或属性进行初始化。
- struct 类型不能从其他 class 或 struct 类型继承,也不能作为 class 基础类型。不过,struct 可以继承接口。
- 不能在 struct 类型中声明终结器(即:析构函数)。
- struct 使用方式,一种通过 new 来创建;另外,也可以使用值类型那样来定义。
- struct 是深度拷贝。
24. 重写和重载的区别
重写:派生类(子类)继承基类(父类),而子类与父类中的方法名、参数、返回类型相同,就称子类重写父类的方法。父类方法必须用关键字 virtual 修饰,子类必须用关键字 override 修饰。
/// /// 父类 /// public virtual void Read() { } /// /// 子类重写 /// public override void Read() { }
重载:在同一个类中,方法名必须相同,参数必须不相同,返回类型可以不相同
public void Test(int x,int y){} public void Test(int x,ref int y){} public void Test(int x,int y,string a){}
25. 构造函数能否被重写
构造函数不能被继承,所以不能被重写,只能被重载。
26. 抽象类和接口的区别
相同点:
- 都不能被实例化
- 可以被继承
- 可以包含方法的声明
- 子类必须实现未实现的方法
不同点:
- 接口不能包含实例字段
- 接口支持多重实现,抽象类只能单一继承
- 接口中没有实现方法体,只负责功能定义,即一个行为的规范;抽象类中的方法可以实现,也可以不实现,有抽象方法的类一定要用 abstract 修饰。
- 接口没有构造方法,抽象类有构造方法
- 抽象类⽤abstract修饰、接⼝⽤interface修饰
- 接口中方法默认是public,抽象类可以用 protected 修饰
- 接口可以继承接口,但不可以继承类,抽象类可以实现接口,而可以继承实现类,如果实现类有构造函数,抽象类必须实现。
public class Person { public string Name { get; set; } public Person(string name) { Name = name; } } public abstract class Annimal : Person { protected Annimal(string name) : base(name) { } }
27. 继承的好处
对父类成员进行重用,增加代码的可读性、灵活性。
28. 当使⽤new B()创建B的实例时,x 和 y 分别输出什么?
class A { public A() { PrintFields(); } public virtual void PrintFields(){} } class B : A { int x = 1; int y; public B() { y = -1; } public override void PrintFields() { Console.WriteLine("x={0},y={1}",x,y); } }
输出:x=1,y=0
这题主要考查的是实例化执行的顺序。
不考虑继承的执行顺序:
- 静态字段
- 静态构造方法
- 实例字段
- 实例构造方法
存在继承关系的执行顺序
- 子类的静态字段
- 子类的静态构造函数
- 子类的实例字段
- 父类的静态字段
- 父类的静态构造方法
- 父类的实例字段
- 父类的实例构造函数
- 子类的实例构造函数
29. 数组和 string 有没有Length()这个方法?
都没有Length()这个方法,只有Length属性。
30. swtich 表达式可以用什么类型? string 类型可以?
swtich 表达式是一个整型(byte、int、long等),字符或字符串类型。
31. using的有哪些用法?
引用命名空间,也可 using 别名;也可以释放资源,实现了 IDisposiable 的类在 using 中创建,using 结束后会自动释放该对象的Disposiable();
先整理这些。
最后,祝大家学习愉快!
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/173816.html原文链接:https://javaforall.net
