JAVA基础

java三大特性

1.封装:只隐藏对象的属性和实现细节,仅对外提供公共访问方式
好处:将变化隔离、便于使用、提高复用性、提高安全性
原则:将不需要对外提供的内容隐藏起来;把属性隐藏,提供公共方法对其访问
2.继承:提高代码复用性;继承是多态的前提
注:
①子类中所有的构造函数都会默认访问父类中的空参数的构造函数,默认第一行有super();若无空参数构造函数,子类中需指定;另外,子类构造函数中可自己用this指定自身的其他构造函数。
3.多态
是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象

好处:提高了程序的扩展性

使用对象无法调用私有方法与属性,只能在该类中使用

非静态方法可以调用静态方法,静态方法不可调用非静态方法,因为静态早于对象存在

弊端:只能访问父类中具备的方法及属性,不可访问子类中特有的的方法和属性;即访问的局限性。

前提:实现或继承关系;重写父类方法。

父类 对象名 = new 子类();   is-a关系
Pet  p1=new Cat();          Pet  p2=new Dog();
p1.eat();                   p2.eat();

必须先有向上转型,才能向下转型,

属性和方法是非静态的话

对于非私有的属性,编译和执行时都看父类(输出父类的值)

对于非私有的方法,编译看左边(父类,检查有没有该方法),执行看右边(子类,执行子类的逻辑)

public class A {
public  String str = "a";
public  void fun(){
        System.out.println("-----A-----");
    }

}

public class B extends A{
public  String str = "b";
public   void fun(){
        System.out.println("-----B-----");
    }

}

public class OO extends A{
public  String str = "oo";
public   void fun(){
        System.out.println("-----oo-----");
    }

public  static void key(){
        System.out.println("-----oo-----");
    }

}

A obg = new B();     
        System.out.println(obg.str);
        obg.fun();
        a
-----B-----
        A kk=new OO();
        System.out.println(kk.str);

        kk.fun();

a

-----oo-----

        B b=(B)obg;
        System.out.println(b.str);

        b.fun();

b
-----B-----

如果 属性和方法是静态的话则(静态方法不能实现多态,静态不能被重写属性和方法都调用父类的,

Java 重写(Override)与重载(Overload)

方法重载是指方法名和方法的返回类型都相同,但方法参数不一样。方法重写是相对继承而言的重写的方法名.返回类型,参数类型和参数个数都要求和父类中的一样,只有方法体里面不同

抽象 abstract
抽象方法没有方法体,抽象方法只能出现在抽象类中(接口是特殊的抽象类),抽象方法必须在子类中被方法重写;

只要是class定义的类里面就肯定可以有构造方法。自身不能new,但是子类会调用父类的构造方法,构造方法不能抽象

public abstract class C {
public C(){

}
public void A1(){

}

public abstract void A2();
}

不能与这些关键字共存
final:如果方法被抽象,就需要被重写,而final是不可以被重写,所以冲突。
private:如果方法被私有了,子类无法继承,怎么重写呢。
static : 不需要对象,通过类名就可以调用抽象方法,而调用抽象方法没有意义。 
接口 interface
1.接口不可以被实例化,不能有构造方法
2.接口中的所有属性都是public static final,并自动被实现类拥有
3.接口中的方法都是抽象方法,接口中的方法会自动使用public abstract修饰,
   不能有方法体,实现类必须实现接口中的所有方法
4.一个类可以同时实现多个接口

5.接口可以继承接口,而且可以多继承,也可以多层级继承,接口不能实现接口

public interface In1 {
public void run();

}

public interface In2 extends In1{
public void run2();

}

public interface In3 extends In2{
public void run3();

}

public interface In3 extends In2,In1{
public void run3();
}

内存泄漏

单例造成的内存泄漏,

非静态内部类创建静态实例造成的内存泄漏,

  1. 首先,非静态内部类默认会持有外部类的引用。

  2. 然后又使用了该非静态内部类创建了一个静态的实例。

  3. 该静态实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用,导致Activity的内存资源不能正常回收。

非静态内部类和匿名类内部类都会潜在持有它们所属的外部类的引用,但是静态内部类却不会,AsyncTask和Runnable都使用了匿名内部类,那么它们将持有其所在Activity的隐式引用。如果任务在Activity销毁之前还未完成,那么将导致Activity的内存资源无法被回收,从而造成内存泄漏。解决方法:将AsyncTask和Runnable类独立出来或者使用静态内部类,这样便可以避免内存泄漏。
5、资源未关闭造成的内存泄漏,BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,从而造成内存泄漏
使用ListView时造成的内存泄漏,
如何避免内存泄漏
1、在涉及使用Context时,对于生命周期比Activity长的对象应该使用Application的Context。凡是使用Context优先考虑Application的Context,当然它并不是万能的,
2、对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏。
3、对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null。
4、保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期。
5、对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
1)将内部类改为静态内部类

2)静态内部类中使用弱引用来引用外部类的成员变量

String和StringBuffer,StringBuilder的区别:
1.StringBuffer s3="hello";  //错   String  s3="hello";   //对
2.+在拼接字符串时只能用于String类,不能用于StringBuffer类,它叫追加,不需要进行拼接
3.String是不可变的,StringBuffer是可变的

4.StringBuffer是线程安全的,而String相反

JAVA基础

JAVA基础

  1. 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String

  String最慢的原因:

  String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。以下面一段代码为例:

 

1 String str="abc";
2 System.out.println(str);
3 str=str+"de";
4 System.out.println(str);

 

  如果运行这段代码会发现先输出“abc”,然后又输出“abcde”,好像是str这个对象被更改了,原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。

  而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。

  另外,有时候我们会这样对字符串进行赋值

1 String str="abc"+"de";
2 StringBuilder stringBuilder=new StringBuilder().append("abc").append("de");
3 System.out.println(str);
4 System.out.println(stringBuilder.toString());

  这样输出结果也是“abcde”和“abcde”,但是String的速度却比StringBuilder的反应速度要快很多,这是因为第1行中的操作和

  String str="abcde";

  是完全一样的,所以会很快,而如果写成下面这种形式

1 String str1="abc";
2 String str2="de";
3 String str=str1+str2;

  那么JVM就会像上面说的那样,不断的创建、回收对象来进行这个操作了。速度就会很慢。

  2. 再来说线程安全

  在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

  如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

  3. 总结一下
  String:适用于少量的字符串操作的情况

  StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况

  StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

Map集合:

(1)HashTable:底层数据结构是哈希表,不可存入null键和null值。同步的
Properties继承自HashTable,可保存在流中或从流中加载,是集合和IO流的结合产物
(2)HashMap:底层数据结构是哈希表;允许使用null键和null值,不同步,效率高
TreeMap:
底层数据结构时二叉树,不同步,可排序
与Set很像,Set底层就是使用了Map集合
方法:
V put(K key, V value) ;  void putAll(Map m)
void clear();  V remove(Object key)
boolean containsKey(Object key);  containsValue(Object key);  isEmpty()
V get(Object key); int size(); Collection<V> values()
Set<K> keySet();  Set<Map.Entry<K,V>> entrySet()


2.3、Map集合取出方式:
第一种:Set<K> keySet()
取出Map集合中的所有键放于Set集合中,然后再通过键取出对应的值
Set<String> keySet = map.keySet();
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
String value = map.get(key);
//…..
}
第二种:Set<Map.Entry<K,V>> entrySet()   iterator()
取出Map集合中键值对的映射放于Set集合中,然后通过Map集合中的内部接口,然后通过其中的方法取出
Set<Map.Entry<String,String>> entrySet = map.entrySet();
Iterator<Map.Entry<String,String>> it = entrySet.iterator();
While(it.hasNext()){
Map.Entry<String,String> entry = it.next();
String key = entry.getKey();
String value = entry.getValue();
//……
}
第三种 entrySet()遍历key和value
for(Map.Entry<String, String> entry:map.entrySet()){
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
2.4、Collection和Map的区别:
Collection:单列集合,一次存一个元素

Map:双列集合,一次存一对集合,两个元素(对象)存在着映射关系

成员变量和局部变量区别
1. 作用范围
成员变量:定义在类中,即属性,可以被类中的任意方法访问。
局部变量:只在它所属的局部大括号中有效,一般出现在某个方法中。

2. 存储情况
成员变量(非静态):存储在堆内存中,随着对象的存在而存在。当对象变成垃圾被回收时,该该对象中的成员变量会消失。
局部变量:存储在栈内存中,当方法被调用,或者语句被执行的时候,才存在。
当方法运行完毕,或者语句运行完毕时,局部会被自动释放,所以成员变量也称之为实例(对象)变量。


3. 初始化情况
成员变量:在堆内存中有默认初始化值。
局部变量:必须手动初始化后,才可以被使用。