`
longgangbai
  • 浏览: 7339564 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】 不用中间变量,实现两个变量的交换

阅读更多

常见的面试题,很简单,但值得细想的问题还是很多,总结解法如下:

(1)加减法:

       int a =10,b=5;

       a = a+b;

       b = a-b;

       a = a-b;

       System.out.println("a=" + a);
       System.out.println("b=" + b);

   原理:其实是用a做中间变量;

   问题:(1)内存溢出,有人提出这种解法如果a,b的值非常大时可能会溢出,即a=a+b;可能会超出Int范围;

              而实际上加法造成的溢出后面的减法会溢出回来,所以这种算法不会产生内存溢出问题,可以自己测试。

           (2)精度损失,对应float和double类型,会造成精度损失;

                    float a =3.123456f;
                    float b=1234567.000000f;

                    交换完后:a=1234567.0; b=3.125;

                    如果是double类型;交换完后a=1234567.0; b=3.1234559998847544;

  还有人提出a=a*b;b=a/b;b=a/b;原理和加减法一样,同样存在精度损失问题;

(2)异或法:

      int a =10,b=5;

       a^=b;

       b =a^b;

       a = a^b;

       System.out.println("a=" + a);
       System.out.println("b=" + b);

       原理:异或就是将十进制转化成二进制0和1,进行位操作;

      问题:float,double类型的无法异或;

(3)内嵌汇编    


    a=1, b=-2;   

 _asm    {     

   push a     

   push b     

   pop  a       

    pop  b   

   }   

 printf("a=%d, b=%d\n", a, b);

原理不清楚(4)

最猛的办法(哈哈,绝了):    

   int a = 3;        int b = 2;    

    printf("a = %d,b = %d", b, a);

 

 

 

 

Java容易搞错的知识点-觉得基础扎实的来看

以下几个知识点是非常容易搞混的Java知识点。大家不准开编译器,并且先不看答案,要是能全部答对,那Java基础是挺牢固的。如果答对了,还能分析出具体原因,那算你NB。近段时间有参加一些公司的面试,做了一些基础题,发现总有掌握得不好的地方。今天一并总结了这些问题,希望对大家有所帮助。如果大家认为还有其它易混淆的地方,也可以跟贴发出来,大家一起讨论。从大家的回贴中,发现了不少自已不知道的东西,想看的就看吧。
一、关于Switch
代码:

Java代码 复制代码 收藏代码
  1.   
public class TestSwitch {
	public static void main(String[] args) {
		int i = 2;
		switch (i) {
		case 1:
			System.out.println(1);
		case 2:
			System.out.println(2);
		case 3:
			System.out.println(3);
		default:
			System.out.println(4);
		}
	}
}





结果:
2
3
4

分析:
少了break;所以2以下的case和default都执行了一遍。

二、Equals和==运算符
代码:

Java代码 复制代码 收藏代码
  1.  
	public static void test() {
		String x = "hello";
		String y = "world";
		String z = new String("helloworld");
		String a = "helloworld";
		System.out.println("x+y equals z:" + (x + y).equals(z));
		System.out.println("a == z:" + (a == z));
		System.out.println("x == hello:" + (x == "hello"));
		System.out.println("a == helloworld:" + (a == "hello" + "world"));
		System.out.println("a == x+y:" + (a == (x + y)));
	}





结果:
x+y equals z:true
a == z:false
x == hello:true
a == helloworld:true
a == x+y:false

分析:
1.String.equals()方法比较的是字符串的内容,所以(x + y).equals(z)为true.
2.“==”比较的是 String 实例的引用,很明显 a 和z 并不是同一个 String 实例,所以(a == z)为false.
3.根据常量池的知识,容易得知(x == "hello")和(a == "hello" + "world")都为true.
(常量池指的是在编译期被确定并被保存在已编译的.class 文件中的一些数据。它包含了
关于方法、类、接口等,当然还有字符串常量的信息。也就是所谓的持久代。)
4.那么(a == (x + y))为什么是false呢?这点暂点有点不大清楚。初步认为是x+y是引用相加,不能放入常量池。

三、Override覆盖
代码:

Java代码 复制代码 收藏代码
public class Parent {

	public static String say() {
		return "parent static say";
	}

	public String say2() {
		return "parent say";
	}
}

public class Child extends Parent {
	public static String say() {
		return "child static say";
	}

	public String say2() {
		return "child say";
	}
}

/**
 * @author 子弹哥
 * 
 */
public class OverrideTest {

	public static void main(String[] args) {
		Parent p = new Child();
		System.out.println(p.say());
		System.out.println(p.say2());

	}

}






结果:
parent static say
child say
分析:
1.我们创建了一个Parent类的实例。变量 p 的数据类型为 Parent 类 但是它仍旧是 Child 类的一个实例。因为Child类覆盖了Parent类的方法say2(),所以p.say2()调用为子类的方法。
2.为什么p.say()却是调用父类Parent的方法呢?因为Java中规定“实例方法被覆盖,静态方法被隐藏”.
关于Override的一些规则:
用子类的静态方法隐藏父类中同样标识的实例方法是不合法的,编译器将会报错;
用子类的实例方法覆盖父类中同样标识的静态方法也是不合法的,编译器同样会报错;
带关键字 final的方法(静态和实例方法)都不能被覆盖;
实例方法能够被覆盖;
抽象方法必须在具体类中被覆盖。

四、Java强类型
代码:

Java代码 复制代码 收藏代码
/**
 * @author 子弹哥
 * 
 */
public class Type {

	public static void main(String[] args) {
		double i = 5.0;
		double j = 1 / 4 + 3 / 4 + i + 12 / 6.0 + 3 / 4 + 1 / 4;
		System.out.println(j);
	}

}








结果:
7.0

分析:
Java 是强类型的 strongly type,它支持8 种基本数据类型。通过对这些基本数据类型用法的严格检查 Java 编译器能够及时地在开发过程中捕捉到许多简单细微的错误。基本数据类型的转换可以隐性地发生,所以转换时会有精度损失。由于1/4和3/4发生隐性类型转换,精度损失,不会生成0.25和0.75,所以有分号的数都为0。

五、假构造函数
代码:

Java代码 复制代码 收藏代码
/**
 * @author 子弹哥
 * 
 */
public class Constructor {

	private int a, b, c;

	public void Constructor() {
		a = 3;
		b = 5;
		c = a + b;
	}

	public void test() {
		System.out.println("The value of c :" + c);
	}

	public static void main(String[] args) {
		Constructor c = new Constructor();
		c.test();
	}
}








结果:
The value of c :0

分析:
public void Constructor()并不是一个真正的构造函数,而是一个方法。所以c的值为默认值0.


六、提前引用
代码:

Java代码 复制代码 收藏代码
/**
 * @author 子弹哥
 * 
 */
public class ForwardReference {

	static int first = test();
	static int second = 2;

	static int test() {
		return second;
	}

	public static void main(String[] args) {
		System.out.println("first = " + first);
	}

}





结果:
first = 0

分析:
由于在初始化second之前test方法就访问了它,那么方法得到的是second的默认值,即 0。 因此输出结果first= 0,而不是2。假如你使用方法调用来初始化静态变量,那么你必须保证 这些方法并不依赖于在它们之后声明的其它静态变量。静态变量以及静态初始化块是在类被加载进 JVM 时执行初始化操作的。Java 语言规范8.5节指出“静态初始化块和静态变量是按照其在代码中出现的顺序依次执行初始化操作的,而不能在类变量声明出现之前就引用它”。


七、对象引用
代码:

Java代码 复制代码 收藏代码
/**
 * @author 子弹哥
 * 
 */
public class TestRef {

	public static void main(String[] args) {
		StringBuffer a = new StringBuffer("a");
		StringBuffer b = new StringBuffer("b");
		append(a, b);
		System.out.println(a.toString() + "," + b.toString());
		b = a;
		System.out.println(a.toString() + "," + b.toString());
	}

	public static void append(StringBuffer a, StringBuffer b) {
		a.append(b);
		b = a;
	}
}







结果:
ab,b
ab,ab


分析:
大家来分析一下这题,我还没有完全理解。
我的分析,可能是错的,哈哈,算是抛砖引玉。

1.a.append(b);-->ab 。因为a是引用,所以调用a的方法,相当于直接调用jvm中的a,所做的append也相当于直接在对象上操作,生效。
2.append方法中第一次b=a,-->b。因为a,b都为main方法内局部变量,跨append方法作用域b对a的引用不生效。
3.main方法中第二次b=a,-->ab。因为在同一作用域方法中,b对a的引用生效,。

 

关于最后一题的话,由于java方法传值是值传递,所以方法里面的ab虽然和方法外的ab指向的对象一样,但是这两个引用在栈中的位置不一样。

过程大概是首先在栈中复制引用a为a',b为b',并令a'指向a所指的在堆中的StringBuffer对象,b'指向b所指的在堆中的StringBuffer对象。
因此方法中的b=a只是起到了b'=a'的作用,并没有影响方法外b的指向。

对象引用
java是按值传递,对象类型的话,分为栈上的引用和堆上的对象,栈上的引用被复制一份,如果操作堆上的对象则对象改变,但是如果操作引用则不改变

 

 

分享到:
评论

相关推荐

    示例代码:不经过中间变量交换两个数

    - C语言中实现不使用中间变量交换两个数的具体步骤 - 代码逻辑分析及注意事项 #### 位运算符的概念与应用 位运算符是在计算机科学中用于对二进制位进行操作的一类运算符。常见的位运算符包括按位与(`&`)、按位或...

    给两个整型变量赋值,然后交换两个变量的值,最后输出交换后的变量值。

    给两个整型变量赋值,然后交换两个变量的值,最后输出交换后的变量值。

    Java不使用中间变量交换两个数

    在编程中,交换两个数值是常见的操作,但不使用中间变量进行交换可能需要一些巧妙的技巧。本文将探讨如何在Java中实现这一目标,主要基于数的中和原理,即通过特定的运算使得两个数相互抵消,从而达到交换的目的。 ...

    02交换两个变量的值

    本篇文章将深入探讨在编程语言中如何实现两个变量值的交换,并通过具体的示例代码进行详细讲解。主要涉及的知识点包括变量声明、赋值操作以及使用第三个辅助变量进行值交换的方法。 #### 变量声明与初始化 在任何...

    JS实现不用中间变量temp 实现两个变量值得交换方法

    在JavaScript编程中,有时我们需要交换两个变量的值而无需使用额外的中间变量。这在内存管理有限或希望优化代码的情况下特别有用。以下是三种常见的方法来实现这个目标: 1. **加减法交换**: 这是最直观的方法,...

    一种不需要中间变量交换两个变量内容的方法

    标题中的“一种不需要中间变量交换两个变量内容的方法”是指在编程中实现两个变量值互换的一种技巧,通常在C语言或其他编程语言中,我们会使用一个额外的中间变量来完成这个任务。然而,描述中提到的朋友分享的方法...

    易语言交换变量值

    在易语言中,“交换变量值”是一个常见的操作,用于在两个变量之间互换它们的存储值。这个操作在很多算法和程序逻辑中都有应用,例如排序、数据处理等。 在易语言中,交换变量值有多种方式,可以使用临时变量,也...

    不要采用异或来交换两个变量

    ### 不要采用异或来交换两个变量 #### 引言 在编程领域,尤其是在学习基本算法和数据结构的过程中,我们经常遇到如何交换两个变量值的问题。通常,教科书中会介绍几种方法,其中一种就是利用异或(XOR)操作来实现...

    单变量与双变量遗传算法的实现

    双变量遗传算法处理两个决策变量的问题,基本流程与单变量类似,但在编码和解码过程中会涉及两个变量。编码时,每个个体由两个决策变量的二进制表示组成。解码时,需要将这两个二进制串转换回对应的连续值。 1. **...

    不使用中间变量,交换int型的 a, b两个变量的值。

    总结来说,不使用中间变量交换两个变量的值有多种方法,包括位运算、算术运算、数组存储和对象属性。不同的方法适用于不同的场景,位运算和算术运算通常更快,但需要考虑溢出和数据类型限制;数组存储和对象属性方法...

    Codesys-基于网络变量列表实现两台PLC之间的通讯

    《基于网络变量列表实现两台PLC之间的通讯》 在工业自动化领域,PLC(可编程逻辑控制器)间的通信是至关重要的,它使得设备间的数据交换成为可能,从而实现复杂系统的协调工作。Codesys作为一款广泛应用的PLC编程...

    用异或来交换两个变量能提高速度是错误的

    2. **异或方法**:通过异或运算来实现两个变量值的交换。这种方法被认为是一种“技巧”,但在实际应用中并不推荐使用。 ```c void reverse_by_xor(char* str, int n) { char* begin = str; char* end = str + n ...

    如何在STEP7 WINCC中编写脚本实现2个PLC之间的数据交换?.docx

    定义两个变量,变量A连接到PLC1的M0.0,变量B连接到PLC2的M0.0。这些变量将成为数据交换的桥梁。 2. **编写全局脚本**: - 在WINCC的"全局脚本"中编写C脚本。全局脚本会在指定的周期(如1秒或500毫秒)内执行,...

    用宏实现两个数的交换

    这个宏接受两个参数`a`和`b`,然后通过算术操作实现这两个变量值的交换。 ### 工作原理 当我们调用`swap(x, y)`时,预处理器将按照以下步骤执行: 1. 将`x`和`y`代入宏定义中的`a`和`b`。 2. 展开后的代码实际上...

    网页前端设计JavaScript实现两个变量的交换

    网页前端设计JavaScript实现两个变量的交换适用于JavaScript初学者对变量的声明和使用。 js 是编程语言有很强的逻辑性在里面: 实现这个要求的思路 先怎么做后怎么做,在这个案例当中,先理清思路,我们需要一个临时...

    函数指针来交换两个数

    用一个函数指针来交换两个数

    不用第三方变量交换两数的值

    假设我们要交换两个变量a和b的值,可以采用以下方法: 1. **异或操作**:异或运算符(^)具有交换性质。当一个数与自身进行异或操作时,结果为0;两个不同的数异或会得到它们的异或结果。因此,我们可以这样交换a和...

    交换两个变量的值,不使用第三个变量的方法及实现.pdf

    在编程中,交换两个变量的值是一个常见的操作。标准方法是使用一个临时变量来辅助交换,但有时我们可能希望避免使用额外的存储空间。本文主要介绍了四种不使用第三个变量来交换两个变量值的方法,适用于C/C++编程...

Global site tag (gtag.js) - Google Analytics