[笔记][Java 4 android] [035~044] 内部类、线程和类集框架

【035】内部类和匿名内部类

如:
class A{
     class B{
          //B就是A的内部类
     }
}

编译过后,会生成什么呢~
A.class
A$B.class

tips:内部类生成后会生成外部$内部.class的编译文件

如何生成一个内部类对象呢~
如:
B b = new A().new B();

内部类可以任意使用外部类的成员变量。
A.java
class A{
     int i;
     class B{
          //B就是A的内部类
          int j;
          int funB(){
               int result = i+j;
               return result;
          }
     }
}

test.java
class test{
     public static void main(String args []){
          //如何创建对象
          A a = new A();
          A.B b = new A().new B();
          A.B bb = a.new B();
         
          a.i = 3;
          b.j = 1;
          System.out.println(b.funB());
          bb.j = 2;
          System.out.println(bb.funB());
     }
}


输出为
1
5

匿名内部类,最常用的
①非匿名内部类示例
A.java
interface A{
     public void doSomething();
}

B.java
class B{
     public void fun(A a){
          System.out.println("B类的函数");
          a.doSomething();
     }
}

AImpl.java
class AImpl implements A{
     public void doSomething(){
          System.out.println("DO SOMETHING");
     }
}

test.java
class test{
     public static void main(String args []){
          //生成一个接口实现类对象
          AImpl al = new AImpl();
          A a = al;
         
          B b = new B();
          b.fun(a);
     }
}


结果



Tips:还记得接口和接口的实现类么~接口只有没有函数体的方法,需要创建对应接口的对象,必须要有一个接口实现类来重写这个方法

②匿名内部类
test.java
class test{
     public static void main(String args []){
          B b = new B();
          //直接生成一个A接口的对象,并且复写doSomething()方法
          b.fun(new A(){
               public void doSomething(){
                    System.out.println("这是一个匿名内部类");
               }
          });
     }
}


结果



【036】java中的线程

android是一个多进程的系统
一个进程下存在多个线程




创建线程的方法:
方法1:
定义一个线程类,继承类Thread并重写其中的方法run(),方法run()称为线程体。
例如:
firstThread.java
class firstThread extends Thread{
     public void run(){
          //复写Thread里的run方法
          for(int i = 0;i<20;i++){
               System.out.println("fisrtThread:"+i);
          }
     }
}

test.java
class test{
     public static void main(String args []){
          //生成线程类的对象
          firstThread ft = new firstThread();
          //启动firstThread线程,而不是这样写ft.run();
          ft.start();
          for(int i = 0;i<20;i++){
               System.out.println("main:"+i);
          }
     }
}

Tips:
主函数代码里有三个线程
一个main函数开始线程
一个firstThread对象的start函数开始线程
一个是垃圾回收对象
注意Thread启动和运行的写法

结果


学过线程的相关知识的理解起来应该很容易= =电脑跑太快数值比较小的话,看的不明显

【037】线程·二

1、实现线程的第二种方法
有一个实现接口Runable的类作为线程的目标对象,在初始化一个Thread类或者Thread子类的线程对象时,把目标对象传递给这个线程实例,由该目标对象提供线程体
class RunnableImpl implements Runnable{
     public void run(){
          for(int i = 0;i<13;i++){
               System.out.println("RunnableImpl:"+i);
          }
     }

}

class test{
     public static void main(String args []){
          //生成一个Runnable接口实现类的对象
          RunnableImpl rl = new RunnableImpl();
          //生成一个Thread对象,并将Runnable接口实现类对象作为参数传入
          Thread t = new Thread(rl);
          //start函数~
          t.start();
     }
}


结论:在实际开发过程中,先定义一个实现Runnable接口的类,再把这个实现类的对象作为参数传给Thread类的构造函数,并且生成Thread对象,再启动线程~
(上一课说的继承方法不常用,因为java是单继承,继承了Thread之后的类就不太好扩展了~)

2、线程的常用函数和控制方法

中断线程
①Thread.sleep()     //休眠,时间ms作为参数,注意会抛出异常
class RunnableImpl implements Runnable{
     public void run(){
          for(int i = 0;i<13;i++){
               System.out.println("RunnableImpl:"+i);
               if(i==10){
                    try{
                         Thread.sleep(2000);     //2000休眠
                    }
                    catch(Exception e){
                         System.out.println(e);
                    }
               }
          }
     }
}


②Thread.yield()     //当前线程让出cpu,但是不是说永久让出,只是让出,之后马上进入抢占cpu状态

③设置线程的优先级
getPriority()
setPriority()

class test{
     public static void main(String args []){
          //生成一个Runnable接口实现类的对象
          RunnableImpl rl = new RunnableImpl();
          //生成一个Thread对象,并将Runnable接口实现类对象作为参数传入
          Thread t = new Thread(rl);
          //打印优先级,输出结果为5
          System.out.println(t.getPriority());
          //设置为最大优先级
          t.setPriority(Thread.MAX_PRIORITY);
          //并打印,结果为10
          System.out.println(t.getPriority());
          //设置为最小优先级
          t.setPriority(Thread.MIN_PRIORITY);
          //并打印,结果为1
          System.out.println(t.getPriority());
          //start函数~
          t.start();
     }
}


结论:线程优先级分为1~10,优先级越高,取得cpu的概率越高。

【038】继续线程~~~

1、多线程数据安全

如以下代码:
class MyThread implements Thread{
     int i = 100;
     public void run(){
          while(true){
               //Thread.currentThread()方法是Thread类中的静态方法,可以取得当前执行的线程对象
               System.out.println(Thread.currentThread().getName()+i);
               i--;
               //Thread.yield()方法是Thread类中的静态方法,使得当前线程让出cpu
               Thread.yield();
               if(i<0){
                    break;
               }
          }
     }
}

class test{
     public static void main(String args []){
          //生成线程体对象
          MyThread mt = new MyThread();
          //生成两个Thread对象
          //但是这两个Thread对象公用一个线程体
          Thread t1 = new Thread(mt);
          Thread t2 = new Thread(mt);
          //每一个线程都有名字,可以通过Thread对象的SetName()方法设置线程名字,也可以使用getName()来获取线程的名字
          t1.setName("a");
          t2.setName("b");
          //启动两个线程
          t1.start();
          t2.start();
     }
}

理想的输出应该是
a100
b99
a98
b97
这样的数据

但是会出现如
a100
b100
a99
b99
这样的错误代码

也就是出现了多线程的数据错误,a和b在某个时间段取得了相同的i~
为了让数据不出现这种错误,a读取i值时需要需要锁定权限,b不可以读取i值
更改如下,使用synchronied(this){}方法

class MyThread implements Thread{
     int i = 100;
     public void run(){
          while(true){
               //使得以下代码块成为同步代码块
               Synchronized(this){
                    //Thread.currentThread()方法是Thread类中的静态方法,可以取得当前执行的线程对象
                    System.out.println(Thread.currentThread().getName()+i);
                    i--;
                    //Thread.yield()方法是Thread类中的静态方法,使得当前线程让出cpu
                    Thread.yield();
                    if(i<0){
                         break;
                    }
               }
          }
     }
}


【039】据说视频压缩挂了,至今未出,什么教学内容依旧是个迷……

【040】数组定义

1、数组的静态声明法
int arr [] = {0,1,2,3,4,5};
2、数组的动态声明法
int arr [] = new int[10];
int类的默认值为0
boolean类型的默认值为false;
ASCII类的默认值为空~
3、二维数组
int arr [][] = {{0,1},{2,3},{4,5}};     //静态声明
int arr [][] = new int[3][2];     //动态声明
如arr[2][1]=5;

【041】类集框架

类集框架是一组类和接口,位于java.util包当中,主要用户存储和管理对象,主要分为三大类-集合、列表和映射

1、集合set
集合中的对象不按特定的方式排序,并且没有重复的
2、列表list
集合中对象按照索引位置排序,可以有重复的对象
3、映射map
集合中的每一个元素包含一个键对象和一个值对象,键不可以重复,值可以重复

类集框架的主要结构




一个ArrayList的例子
test.java

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

class test{
     public static void main(String args []){
          //声明一个String类型的对象列表
          ArrayList<String> arrayList = new ArrayList<String>();
          arrayList.add("a");
          arrayList.add("b");
          arrayList.add("c");
         
          arrayList.remove(1);
         
          for(int i = 0;i<arrayList.size();i++){
               String s = arrayList.get(i);
               System.out.println(s);
          }
     }
}




【042】类集框架2

1、Collection和Iterator接口
2、Set和HashSet的使用方法

①Collection接口
boolean add(Object o)          向集合中加入一个对象
void clear()                          删除集合中的所有对象
boolean isEmpty()                判断集合是否为空
remove(Object o)                从集合中删除一个对象的引用
int size()                             返回集合中元素的数目

②Set是Collection接口的子接口,HashSet是Set接口的实现类

③Collection接口是Iterator接口的子接口
hasNext()          游标后是否还有元素
next()               游标所指位置的下一个元素


也就是说
Iterator<---Collection<----Set<----HashSet;
前三个接口的方法被HashSet所实现。
*Iterator:译作迭代器模式,叫做游标模式。

一个例子:
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
class test{
     public static void main(String args []){
          HashSet<String> hashset = new HashSet<String>();
          Set<String> set = hashset;
          //或者这样Set<String> set =new HashSet<String>();
         
          set.add("a");
          set.add("b");
          set.add("c");
          set.add("d");
          set.add("c");
         
          int i = set.size();
          //System.out.println(i);
          //结果为4,重复元素会被忽略掉
         
          set.remove("d");
          //则d被移除
         
          //set.clear();
          //结果set被清空
         
          //System.out.println(set.isEmpty());
          //结果为true
         
          //调用Set对象的Iterator方法,生成一个游标对象,用于遍历整个Set
          Iterator<String> it = set.iterator();
          while(it.hasNext()){
               String s = it.next();
               System.out.println(s);
          }
     }
}





*这几集有编程基础的看起来还是很轻松地= =
这里出现了个泛型对象的概念,也许是我看漏了哪一集-- 0
具体可以看下这篇
Java泛型简明教程
比较杂,遇到再说吧

【043】类集框架3

Map和HashMap

呃,没什么好说的,键值对的数据
例子如下:
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
class test{
     public static void main(String args []){
          HashMap<String,String> hashmap = new HashMap<String,String>();
          Map<String,String> map = hashmap;
         
          map.put("1","a");
          map.put("2","b");
          map.put("3","c");
          map.put("4","d");
          //对应3键的值改成了e
          map.put("3","e");
         
          int i = map.size();
          System.out.println(i);
          //结果为4
         
          map.get("2");
          //取出了键2的值b
     }
}


【044】java的equals函数

equals函数属于Object类,是java最基本的操作函数

1、对象的内容相等需要符合:
①对象的类型相同(使用instanceof操作符进行比较)
②两个对象的成员变量的值完全相同

如:
x.equals(y)
比较x和y是否完全相同

在Object.java中
public boolean equals(object obj){
     return (this == obj);
}


如果直接使用equals,则就直接继承了这个函数体,需要根据实际情况进行复写

例如
User.java
class User{
     String name;
     int age;
    
     public boolean equals(Object obj){
          if(this == obj){
               return true;
          }
          boolean b = obj instanceof User;//注意instanceof是一个操作符,而不是一个函数
          if(b){
               //将obj转型为User对象
               User u = (User)obj;
               //将obj和this的成员变量进行比较,基本数据类型的用== 引用数据类型的用equals()
               if(this.age == u.age && this.name.equals(u.name)){
                    return true;
               }
               else{
                    return false;
               }
          }
          else{
               return false;
          }
     }
}

test.java
class test{
     public static void main(String args []){
          User u1 = new User();
          User u2 = new User();
          User u3 = new User();
         
          u1.name = "zhangsan";
          u1.age = 19;
          u2.name = "lili";
          u2.age = 19;
          u3.name = "zhangsan";
          u3.age = 19;
         
          System.out.println(u1.equals(u2));
          System.out.println(u1.equals(u3));
     }
}



实际情况中,有编辑器来自动生成equals

【045】hashCode()和toString

1、hashCode()也是Object类中的一个方法

散列值就不多说了,大文件完整性验证就是hash验证

map中的键对比是根据键的hashCode来对比的。

User.java
class User{
     String name;
     int age;
     
     public User(){
          
     }
     
     public User(String name,int age){
          this.name = name;
          this.age = age;
     }
     
     public boolean equals(Object obj){
          if(this == obj){
               return true;
          }
          boolean b = obj instanceof User;//注意instanceof是一个操作符,而不是一个函数
          if(b){
               //将obj转型为User对象
               User u = (User)obj;
               //将obj和this的成员变量进行比较,基本数据类型的用== 引用数据类型的用equals()
               if(this.age == u.age && this.name.equals(u.name)){
                    return true;
               }
               else{
                    return false;
               }
          }
          else{
               return false;
          }
     }
     
     public int hashCode(){
          int result = 17;
          //生成一个散列值,习惯上使用31,性能最好
          result = 31 * result + age;
          result = 31 * result + name.hashCode();
          
          return result;          
     }
}


test.java
import java.util.*;

class test{
     public static void main(String args []){
          User u = new User("zhangsan",12);
          
          HashMap<User,String> map = new HashMap<User,String>();
          map.put(u,"abc");
          
          String s = map.get(new User("zhangsan",12));
          System.out.println(s);
          
          
     }
}

*hashCode()以后也是工具实现的

2、toString()是Object类的方法,可以复写

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值