培训第2个月的第23天----知识点(this,super等)

              最近真的是状态太差了,可以说是很懒了,距离上次写博客竟然过了一个星期。昨天去huaxin去面试,他们那也主要找培训的,一进去全是我这么大的,顿时心情不太美妙,还好面试我的不是让我培训。。。。。不过从一点断断续续4点才从那出来,属实有点过分啊。对了,软件公司虽然有竞争关系,但是他们都有联系!!!!!他们都互相认识!!!

               行了,我就不费话了,嘻嘻嘻,下面就是我要说的内容。

一.this和super

               我们都知道,this指向本类,super指向父类,但是他们到底是什么?之前我知道this相当于是指向当前对象本身,但是既然是对象,那么能直接输出打印出地址吗?我做了一个小Demo。

package com.java.text;

public class TextThisAndSuper {
    public static void main(String[] args) {
    	B1 b=new B1();
    	b.b_text();
    //	b.a_text();
    	
	}
}

class A1{
	String a_name="A";
	String a_age="18";
	static int count=19;
	
	public static void a_text() {
		System.out.println("111111111");
	}
}

class B1 extends A1{
	String b_name="B";
	String b_age="5";

		
	public void b_text() {
		//System.out.println(b_name+","+b_age+","+count+"a_name");
		
		//this.a_age="111111";    (B1 this=new B1();? 我们可以想象这个对象是JVM自动给我们创建的,当你类存在时,这个对象就已经存在了,不管你用不用,它就在这里。----自己理解)
		//System.out.println(this+"----"+this.a_age);
		
		//B1 b2=new B1();
		//b2.b_name="BB";
		//System.out.println(b2+"-----"+b2.b_name);
		
		//System.out.println(this+"----"+this.b_name);
		
		A1 a1=new A1();
		a1.a_age="qiao";
		System.out.println(a1.a_age);
		System.out.println(super.a_age);
		System.out.println(a1);
		System.out.println(super.getClass());
	
		
	}
}

/*子类会继承父类的属性(拥有访问权限的),并且当子类中有和父类同名的属性时,子类的属性
 *会将父类中的属性覆盖。静态方法和静态属性都能够被继承,但是静态方法不能够被重写,静态
 *属性时可以被重写的(因为当子类没有同名属性时,会输出父类中的属性值,当子类中有同名属
 *性时,会输出子类的属性值)。
 * */

/*this是什么?其实this就是这个this所在类,也就是当前类的对象!我们通过输出this,可以看到
 *com.java.text.B1@70dea4e,这明显就是一个B1类型的对象地址。 
 *我们知道子类可以继承父类的属性和方法(允许被继承的),所以this对象也会拥有父类中的属性和方法
 *this上实际就是一个对象,它与其他的对象互不影响,他们有不同的内存地址,所以在我们创建一个其他
 *对象后,更改这个对象的属性值,并不会对this对象有任何的影响。
 * */

/*super是什么?我们也可以认为它是一个对象,是一个父类的对象,只不过不允许打印地址。这是和this
 *对象不同的。
 * */

                 在这个小demo中,我们还可以得出一些关于继承的结论:子类会继承父类的属性(拥有访问权限的),并且当子类中有和父类同名的属性时,子类的属性会将父类中的属性覆盖。静态方法和静态属性都能够被继承,但是静态方法不能够被重写,静态属性时可以被重写的(因为当子类没有同名属性时,会输出父类中的属性值,当子类中有同名属性时,会输出子类的属性值)。

                   但是上面的结论很早就知道,这不是我们想要的,所以,在这也得出了关于this的结论:其实this就是这个this所在类,也就是当前类的对象!我们通过输出this,可以看到com.java.text.B1@70dea4e,这明显就是一个B1类型的对象地址。 我们知道子类可以继承父类的属性和方法(允许被继承的),所以this对象也会拥有父类中的属性和方法this上实际就是一个对象,它与其他的对象互不影响,他们有不同的内存地址,所以在我们创建一个其他对象后,更改这个对象的属性值,并不会对this对象有任何的影响。

                    那么super又是怎么一回事?我们也可以认为它是一个对象,是一个父类的对象,只不过不允许打印地址。因为我们可以直接System.out.println(this),而不可以System.out.println(super)。

                     其实对于this,我们可以想象这个对象是JVM自动给我们创建的,当你类存在时,这个对象就已经存在了,不管你用不用,它就在这里。B1 this=new B1();     ----自己理解)   ,但是super却不能直接打印,我也不知道应该怎么理解好。?????

二."=="和equals()方法

                       可以说这个问题是很多面试要考的,区别也很简单,这里我就先码一下。这里我也做了一个小Demo,通过这个Demo还看到一个关于常量池的问题,常量池的问题,一会我会说。

                          我们先来看这个Demo。

package com.java.text;

public class TextEquals {
   public static void main(String[] args) {
	   TextEquals textEquals=new TextEquals();
	   textEquals.text4();
   }
   
   public void text1() {
	  String s1 = "Monday";
	  String s2 = "Monday";
	    if (s1 == s2){
	       System.out.println("s1 == s2");
	       //说明引用s1和s2引用了同一个Monday对象。
	     }
	    else{
	       System.out.println("s1 != s2");
	     }
     }
   
   public void text2() {
	   String s1 = "Monday";
	   String s2 = new String("Monday");
	   
	   if (s1 == s2){
		   System.out.println("s1 == s2");
		 }
	   else{
		   System.out.println("s1 != s2");
		 }
	   if (s1.equals(s2)){
		  System.out.println("s1 equals s2");
		  //输出的不是地址,而是值
		  System.out.println(s1+","+s2);
	   }
	   else{
	      System.out.println("s1 not equals s2");
	   }
	   
	   /*
	    * s1 != s2
          s1 equals s2
        */
   }
   
   public void text3() {
	   String s1 = "Monday";
	   String s2 = new String("Monday");
	   s2 = s2.intern();
	   
	   if (s1 == s2){
		   System.out.println("s1 == s2");
	   }
	   else {
		   System.out.println("s1 != s2");
		 }
	   if (s1.equals(s2)) {
		  System.out.println("s1 equals s2");
	   }
	   else{
	      System.out.println("s1 not equals s2");
	   }
	   /*
	    * s1 == s2
          s1 equals s2
*/
   }
   
   public void text4() {
	   String a="qiao";
	   String b="qiao";
	   String c=new String("yaya");
	   String d=new String("yaya");
	   System.out.println(a==b);
	   System.out.println(c==d);
	   /*
	    * true
          false 
        */
   }
}





/*java中数据类型,可以分为两种:一种是基本数据类型,也叫原始数据类型。byte,char,short,int,long,float,double,boolean
 *8种。他们如果用“==”进行比较,则比较的是他们的值。
 *第二种是引用数据类型,也叫符合数据类型。当他们用“==”进行比较的时候,比较的是他们在内存中的内存地址(因为他们是对象)。
 *java当中所有的类都是继承Object的,Object是所有类的父类(基类)。在Object类中,定义了一个equals方法,这个
 *方法的初始行为是比较两个对象的内存地址。但是这个方法在一些类库中别重写了,例如String,Integer,Date,他们都有
 *自己的实现,而不是比较类在堆内存中的地址了。
 *对于引用数据类型,之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置
 *的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。
 * */

/*字符串缓冲池:程序在运行的时候会创建一个字符串缓冲池,当使用 s1 = "Monday" 这样的表达式创建字符串的时候,程序首
 *先会在这个String(字符串)缓冲池中寻找相同值的对象(注意是表达式创建的时候,才去字符串缓冲池中去找)。在第一个程序
 *中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1,将s2引用s1所引用的对象"Monday"。所以s1
 *和s2指向的是同一个对象,地址也就相同了。
 *而第二种情况,则是通过new 操作符来创建的,所以新创建的对象是新的对象,该对象被创建在堆内存中,一个在缓冲池中,一个在
 *堆内存中,所以这两个对象的内存地址是不同的。
 *
 *总的来说就是:通过表达式创建的字符串会被方到字符串缓冲池中,通过new 操作符创建的字符串对象会被放到堆内存中。
 * */

/*java.lang.String的intern方法:intern()方法,例如:"abc".intern()方法的返回值还是字符串"abc",表
 *面上看起来好像这个方 法没什么用处。但实际上,它做了个小动作:检查字符串缓冲池里是否存在"abc"这么一个字符串,如果存在,
 *就返回池里的字符串;如果不存在,该方法会 把"abc"添加到字符串缓冲池中,然后再返回它的引用。
 * */
 

              在text1()方法中,我们通过表达式来创建了“两个”对象,我们用"=="和equals()方法分别对这两个引用进行比较,发现s1 == s2。我们都知道,java中数据类型,可以分为两种:一种是基本数据类型,也叫原始数据类型。有byte,char,short,int,long,float,double,boolean8种。他们(基本数据类型)如果用“==”进行比较,则比较的是他们的值。第二种是引用数据类型,也叫复合数据类型。当他们(引用数据类型)用“==”进行比较的时候,比较的是他们在内存中(堆内存中)的内存地址(因为他们是对象)。java当中所有的类都是继承Object的,Object是所有类的父类(基类)。在Object类中,定义了一个equals方法,这个方法的初始行为是比较两个对象的内存地址。但是这个方法在一些类库中别重写了,例如String,Integer,Date,他们都有自己的实现,而不是比较类在堆内存中的地址了。对于引用数据类型,之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,在重写后,equals()方法比较的是引用数据类型的值,而不是地址了。

                由于“==”比较的是引用数据类型的地址,所以说明在text1()方法中两个对象引用都指向一个对象"Monday"。这是因为字符串缓冲池:程序在运行的时候会创建一个字符串缓冲池,当使用 s1 = "Monday" 这样的表达式创建字符串的时候,程序首先会在这个String(字符串)缓冲池中寻找相同值的对象(注意是表达式创建的时候,才去字符串缓冲池中去找)。在第一个程序中,s1先被放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1,将s2引用s1所引用的对象"Monday"。所以s1和s2指向的是同一个对象,地址也就相同了。而第二种情况,则是通过new 操作符来创建的,所以新创建的对象是新的对象,该对象被创建在堆内存中,一个在缓冲池中,一个在堆内存中,所以这两个对象的内存地址是不同的。总的来说就是:通过表达式创建的字符串会被放到字符串缓冲池中,当通过表达式创建相同的对象时,就使引用指向这个对象。而通过new 操作符创建的字符串对象会被放到堆内存中。

                这里还要介绍一个方法:java.lang.String的intern方法:intern()方法,例如:"abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方 法没什么用处。但实际上,它做了个小动作:检查字符串缓冲池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会 把"abc"添加到字符串缓冲池中,然后再返回它的引用。

三.常量池

                  我也不说什么是常量池,存在于那个地方,因为我不太懂。今天老师说对于Integer类型,常量池中只有-128到127,这区间的数字会在常量池中,而不再这个范围的数字会在堆内存中。我不知道对不对,所以做了个小Demo。

package com.java.text;

public class TextThisAndSuper {
    public static void main(String[] args) {
    	TextThisAndSuper text=new TextThisAndSuper();
    	//text.text1();
    	//text.text2();
    	//text.text3();
    	text.text5();
	}
    
    public void text1() {
    	//先通过表达式创建,后通过new操作符来创建。   
    	Integer a=10;
    	Integer b=10;
    	System.out.println(a==b);  //true
    	
    	Integer c=new Integer(10);
    	Integer d=new Integer(10);
    	System.out.println(c==d);  //false
    	
    	System.out.println(a==c);  //false
    }
    
    public void text2() {
    	//先通过new操作符来创建,后通过表达式来创建。
    	Integer a=new Integer(10);
    	Integer b=10;
    	System.out.println(a==b);  //false
    }
    
    public void text3() {
    	//超出边界范围,用表达式创建
    	Integer a=255;
    	Integer b=255;
    	Integer c=255;
    	System.out.println(a==b);  //false
    	System.out.println(c==b);  //false
    	System.out.println(c==a);  //false
    }
    
    public void text4() {
    	//超出边界范围,先用new操作符来创建
    	Integer a=new Integer(255);
    	Integer b=255;
    	Integer c=255;
    	System.out.println(a==b);   //false
    	System.out.println(b==c);   //false
    	System.out.println(a==c);   //false
    } 
    
    public void text5() {
    	//在传参的时候进行比较
    	System.out.println(new Integer(255)==255); //true
    	System.out.println(255==new Integer(255)); //true
    }
}

               这个,不好意思,这个Demo和我预期的不太一样,我解释不了这种情况,明天我问问在来回答这个!

四.Map集合的key

               Map集合的key可以重复吗,如果不可以重复那么是将值覆盖吗?键可以为空吗?值可以为空吗?键值可以同时为空吗?如果可以,可以通过key为null来取出对应的value吗?  

package com.java.text;

import java.util.HashMap;
import java.util.Map;

public class TextMap {
    public static void main(String[] args) {
		Map map=new HashMap();
		map.put("one", "one");
		System.out.println(map);  //{one=one}
		//当键存在时,对键进行操作,会进行值的覆盖。
		map.put("one", "two");
		System.out.println(map);  //{one=two}
		map.put("one", null);
		System.out.println(map);  //{one=null}
		map.put(null, null);
		System.out.println(map);  //{null=null, one=null}
		System.out.println(map);
		//通过null键取出值,可以通过null来获取对应的值
		System.out.println(map.get(null));   //null
		map.put(null, "four");
		System.out.println(map.get(null));   //four
	}
}

                得出结论:当键存在时,在次向map集合中存放以存在key,会将key对应的值进行覆盖。键可以为空,值可以为空,键值可以同时为空,可以通过key为null来取出对应的value值。  

五.泛型的意义

               泛型的意义:类型(数据类型)的参数化,就是可以把类型像方法的参数那样传递。这一点意义非凡。

package com.java.text;

import java.util.ArrayList;
import java.util.List;

public class TextGenerics {
	
  public static void main(String[] args) {
	  TextGenerics generics=new TextGenerics();
	  generics.text2();
  }
  
  public void text1() {
	  //验证一下不适用泛型的缺点
	  AAA a=new AAA();
	  a.setStr("1234");
	  List list=new ArrayList();
	  list.add(a);
	  //java.lang.String cannot be cast to java.lang.Integer
	  Integer str_int=(Integer)(((AAA)list.get(0)).getStr());
	  //原本就是String类型,所以可以变为String类型
	  String str_str=(String)(((AAA)list.get(0)).getStr());
	  System.out.println(str_int);
	  System.out.println(str_str);  
  }
  
  public void text2() {
	  List list=new ArrayList();
	  BBB b=new BBB();
	  //不指明泛型  T 那么T就代表Object类型的。
	  b.setT("4321");
	  list.add(b);
	  //可以将Object类型变为String类型
	  String str=(String)((BBB)list.get(0)).getT();
	  System.out.println(str);
	  
	  BBB<String> b2=new BBB<String>();
	  //指明了参数类型为String,传入其他的类型会报错。
	  b2.setT("1234");  
  }
  
  public void text3() {
	  //给集合定义泛型,说明这个集合只能装在这个类型的元素
	  List<String> list=new ArrayList();
	  list.add("1");
  }
}

class AAA{
	//多态,父类引用接收子类对象,实际上的str类型仍然是String类型的。
    private Object str;

	public Object getStr() {
		return str;
	}

	public void setStr(Object str) {
		this.str = str;
	}
	 
}

class BBB<T>{
	//这里的 T 是一种数据类型,通过初始化类的时候,指明参数的类型。
	private T t;

	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}
	
}


/*泛型的意义:类型(数据类型)的参数化,就是可以把类型像方法的参数那样传递。这一点意义非凡。
 * */

             这是自己写的一个Demo,只得出如果不使用泛型,那么会出现编译通过,而运行不通过的情况。这里贴一个链接,讲泛型的:https://www.cnblogs.com/lwbqqyumidi/p/3837629.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值