java基础知识点(一)

自动类型转换:小容量的类型可以自动转换为大容量的类型,这里容量不是指的字节数,而是指的表述范围,比如说long(8个字节)->float(4个字节)

switch语句,从case开始一直到break表示结束
带标签的continue:
    public class TestContinueWithLabels {
    public static void main(String[] args) {
        //输出100到205之间的质数
        outer:for(int i=100; i<=205; i++){
            for (int j=2; j <=i/2; j++){
                if(i%j==0){
                    continue outer;
                }
            }
            System.out.println( i+"");
        }
    }
}

无返回值就指定void,无类型

方法重载:实际上是完全不同完全独立的方法,只不过名称一样
方法里如果加入了static,就可以直接调用而不需要还得先new一个对象才能调用该方法
参数个数不同会造成重载,只有参数名不同不构成重载,只有返回类型不同不构成重载

递归结构中包括两方面:
    递归头部分:什么时候不调用自身方法,如果没有头,将陷入死循环,也就是递归的结束条件;
    递归体:什么时候需要调用自身方法。
    递归比较耗资源。
    
面向过程与面向对象:
    面向过程适合简单,不需要协作的事务。比如说开车,我只要列出1234步就好了,但如果说造车,我列出1234就力不从心了,自然而然的就想到对象object,
    比如说车,有车窗、轮胎、发动机等等,面向对象适合大型的软件开发。

    总结:
        1.都是解决问题的思维方式,都是代码组织的方式。
        2.解决简单问题可以使用面向过程。
        3.解决复杂问题:宏观上使用面向对象把握,微观处理上仍然是面向过程。
        
对象与类:
    对象object,或叫实例instance,带有属性和方法,比如说一个学生,有姓名年龄身高等属性,还有吃饭、睡觉、游戏等方法
    类class,可以看作是一个模板,或者图纸,系统根据类的定义来造出对象。
    构造方法,就是用于构建这个类的对象,无参的构造方法可以由系统自动创建。
    
    
java虚拟机的内存可以分为三个区域:栈stack、堆heap、方法区method area
    栈:每个方法被调用的时候,就会创建一个栈帧。
        1.栈描述的是方法执行(记忆重点)的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
        2.jvm会为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
        3.栈属于线程私有,不能实现线程间的共享!
        4.栈的存储特性是“先进后出,后进先出”
        5.栈是由系统自动分配,速度快!栈是一个连续的内存空间!
    堆:存储对象,当new一个啥的时候就说明在堆里面存储了
        1.堆用于存储创建好的对象和数组(数组也是对象)
        2.jvm只有一个堆,被所有线程共享
        3.堆是一个不连续的内存空间,分配灵活,速度慢!
    方法区:(存储类相关信息)
        1.jvm只有一个方法区,被所有线程共享!
        2.方法区实际也是堆,只是用于存储类、常量相关的信息!
        3.用来存放程序中永远是不变或唯一的内容。(类信息【class对象】、静态变量、字符串常量等)
        
构造方法:
构造方法的第一句总是super()
    4.构造方法名称和类名必须保持一致。
    要点:
        1.通过new关键字调用!
        2.构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return 返回某个值。(但可以使用return;用以结束)
        3.如果我们没有定义构造器,则编译器会自动定义一个无参的构造函数,如果已定义则编译器不会自动添加!
        
垃圾回收机制(garbage collection):
    饭店吃饭(把每一个对象都看做是一张桌子,然后有个服务员叫GC,看到哪个桌子脏了没客人去吃就去擦桌子),而之前C++的却没有GC服务员,
    每张桌子需要顾客吃完了自己擦,如果没擦桌子就脏了,等到每张桌子都脏了之后该饭店也就关了。
    所以GC的作用是:
        1.发现无用的对象
        2.回收无用对象占用的内存空间。
    垃圾回收相关算法:
        引用计数法
        引用可达法(跟搜索算法)
    
    通用的分代垃圾回收机制:不同的对象的生命周期是不一样的。为提高效率,将对象分为:年轻代、年老代、持久代
    其中JVM将内存划分为Eden、Survivor(年轻代)和Tenured/Old(年老代)等,持久代放在方法区中。
    这里不说持久代。
    
    垃圾回收过程:
        1.新创建的对象,绝大部分都会存储在Eden中;
        2.当Eden满了(达到一定比例)不能创建新对象,则触发垃圾回收(GC),将无用对象清理掉,然后剩余对象复制到某个Survivor中,比如S1,同时清空Eden区
        3.当Eden区再次满了,会将S1中的不能清空的对象存到另外一个Survivor中,如S2,同时将Eden中不能清空的对象也复制到S1中,保证Eden和S1均被清理;
        4.重复多次(默认15次)Survivor中没有被清理的对象,则会复制到老年代Old(Tenured)区中。
        5.当Old区满了,则会触发一个一次完整的垃圾回收(FullGC),之前新生代的垃圾回收称为(minorGC)
        
    Minor GC:用于清理年轻代区域。Eden区域满了就会触发一次Minor GC,清理无用对象,将有用对象复制到Survivor1、Survivor2区中(这两个区,大小空间也相同,同一时间只有一个在用,一个为空)
    Major GC:用于清理老年代区域
    Full GC:用于清理年轻代、老年代区域,成本较高,会对系统性能产生影响。
    
_this的本质:
    创建一个对象分为如下四步:
        1.分配对象空间,并将对象成员变量初始化为0或空
        2.执行属性值的显式初始化
        3.执行构造方法
        4.返回对象的地址给相关的变量
            
this的本质就是“创建好的对象的地址”!由于在构造方法调用前,对象已经创建。因此,在构造方法中也可以使用this代表“当前对象”。
    this最常用法:
        1.在程序中产生二义性之处,应使用this来指明当前对象,普通方法中,this总是指向调用该方法的对象,构造方法中,this总是指向正要初始化的对象。
        2.使用this关键字调用重载的构造方法,避免相同的初始化代码,但只能在构造方法中用,并且必须位于构造方法的第一句。
        3.this不能用于static方法中。
            

static关键字:
    在类中,用static声明的成员变量为静态成员变量,也称为类变量。类变量的生命周期和类相同,在整个应用程序执行期间都有效。
    static修饰的成员变量和方法,从属于类,不属于对象。普通变量和方法是从属于对象的。
    
静态初始化块:
    构造方法用于对象的初始化块。静态初始化块,用于类的初始化操作!在静态初始化块中不能直接访问非static成员。
    
    
参数传值机制:
    Java中,方法中所有参数都是“值传递”,也就是“传递的是值的副本”,也就是说,我们得到的是“原参数的复印件,而不是原件”,因此,复印件改变不会影响原件。
    基本数据类型参数的传值:
        传递的是值的副本,副本的改变不会影响原件。
    引用类型参数的传值:
        传递的是值的副本,但是引用类型指的是“对象的地址”。因此,副本和原参数都指向了同一个“地址”,改变“副本指向地址对象的值,也意味着原参数指向对象的值也发生了变化”。
    public class User1 {
    int id;
    String name;
    String pwd;
    public User1(int id,String name){
        this.id = id;
        this.name = name;
    }
    public void testParameterTransfer01(User1 u){
        u.name = "高小八";
    }
    public void testParameterTransfer02(User1 u){
         u = new User1(123,"高三");
    }
    public static void main(String[] args) {
        User1 u1 = new User1(100,"高小七");
        u1.testParameterTransfer01(u1); //将u1传给u,u指向的是与u1同样的地址,那么改变u之后,u1也改变了
        System.out.println(u1.name); //所以结果是高小八
        u1.testParameterTransfer02(u1);
        System.out.println(u1.name);  //这里结果还是高小八,是因为16行new了个新对象,说明就换了个引用地址了,跟u1指向的不是同一个地址,所以u1还是不变
    }
}


Java中类没有多继承,但接口可以多继承
子类重写父类的方法(override,跟方法重载overload不一样)

Object类是所有java类的根基类,也就意味着所有的java对象都拥有object类的属性和方法。
/**
 * 重写toString方法
 */
public class TestObject {
    public static void main(String[] args) {
     //   Object obj;
       TestObject to = new TestObject();
       System.out.println(to); //这里其实就是调用了to.toString方法

    }
    @Override
    public String toString(){
        return "重写的tostring方法!";
    }
}
object类中定义有:public boolean equals(Object obj)方法,提供定义“对象内容相等”的逻辑。
String str1 = new String("TXT");
String str2 = new String("TXT");
System.out.println(str1==str2);//结果为false,因为两者是不同的对象
System.out.println(str1.equals(str2);//结果为true,因为两者内容一样


super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。
super永远位于构造器的第一句,见下例:
public class TestSuper {
    public static void main(String[] args) {
        System.out.println("开始创建第一个childclass对象。。。。。。");
        new ChildClass();
    }
}
class FatherClass{
    public FatherClass(){
    //    super();
        System.out.println("创建father构造器!");
    }
}
class ChildClass extends FatherClass{
    public ChildClass(){
    //    super();
        System.out.println("创建子构造器!!!");
    }
}
这里输出结果依次为:
    开始创建第一个childclass对象。。。。。。
    创建father构造器!
    创建子构造器!!!
为什么会这样,是因为构造器的第一句是super(),无论你有没有写,系统都会有这么一句的,所以上述情况其实是都有个看不见的super存在
在调用new ChildClass时,首先会先进行super(),也就到了fatherclass中了,而fatherclass也有super,所以就到了object中了,所以依次输
出结果是这样。child->father->object

封装:
    封装的实现是通过访问控制符的,java的访问控制符有4个,private,default,protected,public,权限依次越来越大
                同一个类    同一个包中    子类     所有类
    private         +            
    default            +            +            
    protected        +            +            +    
    public            +            +            +        +
    
private表示私有,只有自己类能访问
defau表示没有修饰符修饰,只有同一个包的类才能访问
protected表示可以被同一个包的类以及其他包中的子类访问
public表示可以被该项目的所有包中的所有类访问

封装的使用细节:
    一般写类都将其属性都设为private,外部类就访问不到,要想给其访问就对属性设置相应的set和get方法,比如说setName,getName等函数,
    这也就是javabean,一个完整的javabean,要有set和get方法,还要有空的构造器。
    
    
多态:指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。
多态的要点:
    1.多态是方法的多态,不是属性的多态(多态与属性无关)。
    2.多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。(必须三个都有)
    3.父类引用指向子类对象之后,用该父类引用调用子类重写的方法,此时多态就出现了。
    
    public class TestPolym {
    public static void main(String[] args) {
        Animal a = new Animal();
        AnimalCry(a);

        Dog b = new Dog();
        AnimalCry(b);  //这里就是父类引用指向子类对象,(b是子类,但参数其实是父类对象)所以一共满足多态的三个必要条件,就产生了多态,如果没有多态,要想产生同样的效果就比较繁杂了,
        // 就需要写很多次的AnimalCry,每个子类写一个
    }
    static void AnimalCry(Animal a){
        a.shout();
    }
//    static void AnimalCry(Dog a){
//        a.shout();                    //像这样
//    }
    //    static void AnimalCry(Dog a){
//        a.shout();
//    }
}

class Animal{
    public void shout(){   //这里有方法重写也有继承
        System.out.println("叫了一声!!!");
    }
}
class Dog extends Animal{
    public void shout(){
        System.out.println("汪汪汪!!!");
    }
}
class Cat extends Animal{
    public void shout(){
        System.out.println("喵喵喵喵!!!");
    }
}


final关键字
    1.修饰变量:被final修饰的变量不可改变,一旦赋了初值,就不能被重新赋值。
    2.修饰方法:该方法不可被子类重写,但是可以被重载。
    3.修饰类:修饰的类不能被继承。比如:Math、String等
    
    
数组初始化:
    1.静态初始化:int a = {0,2,4};
    2.默认初始化:int a = new int[3];
    3.动态初始化:int a = new int[3];a[0]=1;
    

    
//自动装箱:编译器自动将数据类型转换为包装类 Integer a = 234;实际上编译器是Integer a = Integer.valuesOf(234)
//自动拆箱:编译器自动将包装类转换为数据类型 int b = a;实际上编译器是做了int b = a.intValue()操作。

//String是不可变的,因为源码中的char前有final修饰
//StringBuilder是可变的,因为char中没有用final修饰,同理StringBuffer也是一样
//StringBuilder(线程不安全,效率高)和StringBuffer(线程安全,效率低),一般常用StringBuilder,因为线程不安全很少考虑

StringBuilder有个方法:insert(index,插入字符)可以链式调用,观察源码:是因为其调用了return this,返回了其本身


1.Date时间类,2.时间格式化类DateFormat(把时间对象转换成字符串对象,把字符串对象转换成时间对象)
3.Calendar日期类 new GregorianCalendar(2999,10,9,22,10,50)


异常类层次结构图
throwable
    1.Error(不需要我们管的,类似于开车发动机坏了司机怎么操作都没用,表示jvm已经处于不可恢复的崩溃状态中)
    2.Exception
        1.Checked Exception:已检查异常。编译器处理,一般像语法异常啊。。。
        2.Runtime Exception:也叫unchecked exception,运行时异常,多数由程序员自身的逻辑错误产生。

try-catch-finally:这里的finally语句,无论前面是经过哪一步的,最后都会走finally语句块,只有在一种情况下例外,
如果在执行finally语句块之前遇到了System.exit(0)结束程序运行。        
        
    
容器collection(interface):
    数组就是一种容器,可以在其中放置对象或基本类型数据
    1.set(interface没有顺序,不可重复,也只能放一个null):collection有的方法它都有,也没有新增的像list关于索引等方法
        hashset是采用哈希算法实现,底层实际是用hashmap实现的(hashset本质上就是一个简化的hashmap),因此查询和增删效率都比较高。
    2.List(interface有顺序,可重复)
        1.ArrayList:底层是数组,可以进行扩容。查找效率高,增删效率低,线程不安全
        2.LinkedList:底层是双向链表。增删效率高,查找效率低,线程不安全
        3.Vector:底层是数组,相关方法都加了同步检查,“线程安全,效率低”。
        一般的,只有要求是线程安全的时候,才会使用vector,其他情况都不怎么使用它,而是选择其他两者。
    3.Map(interface):Key-Value形式,底层是数组加链表,结合两者特点,熟记Map的储存方式与查找方式(与key的hashcode值所产生的hash有关)
        1.hashmap:线程不安全,效率高,允许key或value为null
        2.hashtable:线程安全,效率低,不允许key或value为null

理解泛型:考虑一个一个的容器里,我要放入猪肉跟羊肉,如果放在同一个容器里,取出来的时候就得注意是否是想要的羊肉,
那么泛型就是,我把猪肉跟羊肉放入不同的容器里,并且还写有标签,那么我再想要羊肉的话就可以直接取不用再看了。
那么泛型不正规的说就是相当于在容器上添加一个标签,可以帮助我们建立类型安全的集合。
用专业化的话来说,泛型的本质就是“数据类型的参数化”。我们可以把泛型理解为数据类型的一个占位符(形式参数),即告诉
编译器,在调用泛型时必须传入实际类型。
public class TestGeneric {
    public static void main(String[] args) {
        MyCollection<String> mc = new MyCollection<String>();
        mc.set("didi",0);
    //    mc.set(1111,1); //这里开始就不行了,因为泛型是String,而这里是整型
        String a = mc.get(0);
      //  int b =(int)mc.get(1);
        System.out.print(a);
    }
}
class MyCollection<E>{
    Object[] objs = new Object[5];
    public void set(E e,int index){
        objs[index] = e;
    }
    public E get(int index){
        return (E)objs[index];
    }
}

TreeMap:底层是红黑二叉树,在排序的时候用
Comparable接口:中有个compareTo方法,其中比较大小如果为负数表示小于,0表示相等,1表示大于,要想倒序,将正负1换下即可
TreeSet:底层实际是用TreeMap写的,内部维持了一个简化版的TreeMap,通过key来存储Set的元素,TreeSet内部需要对存储的元素进行
排序,因此,对应的类需要实现Comparable接口,这样根据compareTo()方法比较对象之间的大小,才能进行内部排序。
    

Iterator迭代器遍历容器元素(List/Set/Map),统一的遍历容器的方式:
public class TestIterator {
    public static void main(String[] args) {
   // listIterator();
    //    setIterator();
    //    mapIterator1();
        mapIterator2();
    }
    public static void listIterator(){
        List<String> list = new ArrayList();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        for(Iterator<String> iter=list.iterator();iter.hasNext(); ){
            String temp = iter.next();
            System.out.println(temp);
        }
    }
    public static void setIterator(){
        HashSet<String> set = new HashSet<>();
        set.add("aa1");
        set.add("bb2");
        set.add("cc3");
        for(Iterator<String> iter=set.iterator();iter.hasNext();){
            String temp = iter.next();
            System.out.println(temp);
        }
    }
    //map的迭代器与list/set有所不同。要先根据map生成set,然后再iterator
    //这是第一种方式:先由map生成entrySet,然后由entrySet生成iterator进行迭代
    public static void mapIterator1(){
        HashMap<Integer, String> map1 = new HashMap<>();
        map1.put(1,"aaa");
        map1.put(2,"ccc");
        map1.put(3,"ddd");
        Set<Map.Entry<Integer, String>> ss = map1.entrySet();

        for(Iterator<Map.Entry<Integer, String>> iter= ss.iterator(); iter.hasNext();){
            Map.Entry<Integer, String> temp = iter.next();
            System.out.println(temp.getKey()+"——————"+temp.getValue());
        }
    }
//第二种方式,就是先由map获得该map的keySet,然后再遍历该keySet,再获取相应的value值。
    public static void mapIterator2(){
        HashMap<Integer, String> map2 = new HashMap<>();
        map2.put(1,"aaa");
        map2.put(2,"ccc");
        map2.put(3,"ddd");
        Set<Integer> ks = map2.keySet();
        for(Iterator<Integer> iter= ks.iterator();iter.hasNext();){
            Integer temp = iter.next();
            System.out.println(temp.toString()+map2.get(temp));
        }
    }
}

Collections工具类与collection接口不同,有很多方法,比如说:
 Collections.sort(list); 排序
 System.out.println(Collections.binarySearch(list,"dai:1")); 二分查找某个元素是否在list中
 Collections.reverse(list); 逆序
 Collections.shuffle(list); 洗牌
       

IO:
    在整个java.io包中最重要的就是5个类和3个接口,掌握了这些IO的核心操作
    5个类:
        1.File类:数据源,文件类
        2.InputStream:字节输入流(我们操作的数据有两种:字符跟字节)
        3.OutputStream:字节输出流
        4.Reader:字符输入流
        5.Writer:字符输出流
    3个接口:文件不是直接存在java中,而是存在硬盘中,那这个硬盘就需要操作系统去操作,因此java程序需要跟操作系统进行交流,
    当java已经读完了这个文件,需要告诉操作系统可以释放你操作系统该文件的资源了,这里就涉及到流关闭接口了。
        1.Closeable:关闭流接口
        2.Flushable:刷新流接口
        3.Serializable:序列化接口
        当我们手上拿到一个对象的时候,如果放在内存中,当电脑一关,数据就没了,因此为了便于对对象的传输,定期
        将其存储到存储文件中,这时候我们就把这种存储对象称作序列化。
        
流分类1:(按直接操作数据源还是间接操作数据源来分)
    字节流:直接从数据源或目的地读写数据
    处理流(包装流):不直接连接到数据源或目的地,是其他流进行封装。目的主要是简化操作和提高性能。
    节点流和处理流的关系:
        1.节点流处于io操作的第一线,所有操作都必须通过他们进行;
        2.处理流可以对其他流进行处理(提高效率或操作灵活性)。
流分类2:按数据类型分为字节流跟字符流(底层还是基于字节流操作,自动搜索了指定码表)。
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值