C#编程(六十二)---------LINQ标准的查询操作符

LINQ标准的查询操作符

首先我们来看一下LINQ的操作符,可根据查询操作符的操作”类型”进行分类,如把它们分成投影,限制,排序,联接,分组,串联,聚合,集合,生成,转换,元素,相等,量词,分割等.


类型


操作符名称


投影操作符


Select,SelectMany


限制操作符


Where


排序操作符


OrderBy,OrderByDescending,ThenBy,ThenByDescending,Reverse


联接操作符


Join,GroupJoin


分组操作符


GroupBy


串联操作符


concat


聚合操作符


Aggregate,Average,Count,LongCount,Max,Min,Sum


集合操作符


Distinct,Union,Intersect,Except


生成操作符


Empty,Range,Repeat


转换操作符


AsEnumerable,Cast,OfType,ToArray,ToDictionary,ToList,ToLookup


元素操作符


DefaultIfEmpty,ElementAt,ElementAtOrDefault,First,Last,FirstOrDefault, LastOrDefault,Single,SingleOrDefault


相等操作符


SequenceEqual


量词操作符


All,Any,Contains


分割操作符


Skip,SkipWhile,Take,TakeWhile

演示案例:

using System;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace LINQ查询操作符

{

class Program

{

static void Main(string[] args)

{

//将这些Person类的实例化对象存放到list1中

IEnumerable<Person> list1 = GetMyList();

//使用LINQ的过滤操作符

var query1 = from p in list1 where p.age >= 20 select p;

Console.WriteLine("将年龄大于20的人输出出来 : ");

PrintMyInfo(query1);

//下面我们写一个对象查询的版本

Console.WriteLine("对象版本的过滤 : ");

list1 = list1.Where<Person>(per => { return per.age >= 30; }).Select(per => per);

PrintMyInfo(list1);

/*索引过滤

* 这是一个无法使用LINQ语句来实现的功能,它是where方法的重载

* 在这个方法中,可以穿入第二个参数----索引

* 可以是过滤器返回个数的计数器,可以在表达式中使用这个索引,执行基于索引的计算

* public delegate TResult Func<T1,T2,TResult>(T1 arg1mT2 arg2);委托重载

*/

IEnumerable<Person> list2 = GetMyList();

list2 = list2.Where<Person>((p1, p2) => p1.name.StartsWith("a") && p2 <= 1);//从0开始计数

Console.WriteLine("只输出姓名以a字母开头的,并且只要两个人,多了不要");

PrintMyInfo(list2);

/*

* 类型过滤

* 假定一个数组包含有整型,与字符型元素,而我们只想过滤出字符型元素.

*/

object[] objs = new object[] { 232, 23, 3232, "syx", 343, 23456, "zsf" };

//就是这么牛,不用解释

var query2 = objs.OfType<string>();

Console.WriteLine("类型过滤,只要string类型的 :");

foreach (var item in query2)

{

Console.WriteLine(item);

}

/*复合的form子句

* 如果需要根据对象的一个成员过滤,而该成员本身又是一个个系列,就要用到复合子句.

* 案例:我们想找一个年龄在25以上,并且有奔驰的人(一个人可以有多个车),认他当干爹

*/

IEnumerable<Person> list3 = GetMyList();

Console.WriteLine("认干爹的任务 : ");

var query3 = from p in list3 from c in p.list where c.name.Equals("奔驰") where p.age >= 25 select p;

PrintMyInfo(query3);

/*

* 下面来分析一下select投影方法

* public static Ienumerable<TResult> Select<TSource,TResult>(this IEnumerable<TSource> source,Func<TSource,TResult> selector)

* Select<TSource,TResult>方法定义了两个泛型类型,源,返回类型

* IEnumerable<TResult>返回可以迭代的类型

* 两个参数: this IEnumerable<TSource> source 是指本方法要扩展IEnumerable<TSource>类型

* Func<TSource, TResult> selector委托

* 委托的声明: public delegate TResult Func<T, TResult>(T arg)

*/

IEnumerable<Person> list4 = GetMyList();

var query4 = list4.Select(p => p.age);

/*

* select第一个参数是隐式的,所以我们不用关心,只要明白它是扩展就可以了,

* 第二个参数通过源类型,返回一个投影类型,可以是源类型的一个字段,也可以将

* 源类型直接返回,也就是我们直接写select p

* 以上实例,我们是将源类型中的age返回,它是int类型.下面我们迭代,就不可以用Person来迭代了

*/

Console.WriteLine("年龄投影");

foreach (var item in query4)

{

Console.WriteLine(item);

}

/*

* 在select和where这两个方法上,可能会存在一点误解,我开始认为select和where可以做相同的问题

* 比如,都是可以进行筛选

*/

var query5 = list4.Select(p =>

{

if (p.age >= 25)

{

return new Person(p.name, p.age);

}

else

{

return new Person("node", 1);

}

});

/*

* 上述代码是用来过滤年龄超过25岁的人,但是无法将不需要的部分清楚,所以

* 还是没办法与where一样的功能.

* where方法,返回的是bool,可以筛选不合格条件的

*/

Console.WriteLine("select模拟where");

foreach (var item in query5)

{

Console.WriteLine(item.name);

}

//看完了select我们接着看SelectMany方法,其实复合查询中,就是用到了这个方法。

//public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(

//    this IEnumerable<TSource> source,

//    Func<TSource, IEnumerable<TCollection>> collectionSelector,

//    Func<TSource, TCollection, TResult> resultSelector

//)

//返回IEnumerable<TResult>

//3个参数,第一个是隐式的,也就是指明他扩展的是哪种类型的this IEnumerable<TSource> source

//第二个参数,是一个委托 Func<TSource, IEnumerable<TCollection>> collectionSelector,

//下面我们看这个委托的声明:public delegate TResult Func<T, TResult>( T arg )

//这里与select方法有一点不同,select用委托做参数时保留了TResult类型,而这里我们指定成了IEnumerable<TCollection>>

//第三个参数,同样也是一个委托 Func<TSource, TCollection, TResult> resultSelector

//public delegate TResult Func<T1, T2, TResult>(T1 arg1,T2 arg2)

IEnumerable<Person> list5 = GetMyList();

//以下实例是SelevtMany方法的一个重载,只是将一个序列的子集序列查出来

var query6 = list5.SelectMany(per => per.list).Where(p => p.name.Equals("奔驰"));

Console.WriteLine("查询序列的序列 :");

foreach (var item in query6)

{

Console.WriteLine(item.name);

}

//用对象方法的方式来查询一次所有25岁以下的拥有奔驰的干爹

var query7 = list5.SelectMany(cars => cars.list, (per, car) => new { Person = per, Cars = car }).Where(p => p.Person.age >= 25 && p.Cars.name.Equals("奔驰")).Select(par=>par.Person.name);

Console.WriteLine("对象凡是复合查询");

foreach (var item in query7)

{

Console.WriteLine(item);

}

/*

* 案例:把人按照年纪排一次序

*/

var query8 = list5.Select(p => p).OrderBy(p => p.age).ThenBy(p => p.name);

var query9 = list5.Select(p => p).OrderByDescending(p => p.age).Take(2);

Console.WriteLine("升序排列所有人 :");

PrintMyInfo(query8);

Console.WriteLine("降序排列所有人 :");

PrintMyInfo(query9);

/*

* 分析:OrderBy与OrderBydescending方法都是返回IOrderedEnumerable<TSource>接口类型

* 这个接口扩展自IEnumerable<T>

* public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>

* (this IEnumerable<TSource> source,Func<TSource, TKey> keySelector)

*/

/*

* 分组

* 下面我们使用LINQ语句实现分组查询,我们把认得年纪分组,我们只接受元素大于两个的组

* 每一组我们按个数排序,如果个数相同,我们按年纪相同

*/

var query10 = from per in list5

group per by per.age into g

orderby g.Count(), g.Key

where g.Count() >= 2

select new { Age = g.Key, Count = g.Count() };

Console.WriteLine("分组查询 : ");

foreach (var item in query10)

{

Console.WriteLine(item.Age+"====="+item.Count);

}

//方式方法实现上面功能

var query11 = list5.GroupBy(per => per.age)

.OrderBy(p => p.Count()).ThenBy(p => p.Key)

.Where(p => p.Count() >= 2)

.Select(p => new { Age = p.Key, Count = p.Count() });

Console.WriteLine("分组查询,方式方法 : ");

foreach (var item in query11)

{

Console.WriteLine(item.Age+"====="+item.Count);

}

/*

* 对嵌套的对象分组

* 如上所示,我们将年龄分组,如果要把组内人员的名字一并返回,势必会将名字当做一个序列

* 此时,它是一对多的关系

*

*/

Console.WriteLine("嵌套对象分组 :");

var query12 = list5.GroupBy(per => per.age)

.OrderBy(p => p.Count()).ThenBy(p => p.Key)

.Where(p => p.Count() >= 2)

.Select(p => new { Age = p.Key, Count = p.Count(), Persons = from per in p orderby per.name select per });

foreach (var item in query12)

{

Console.WriteLine(item.Age+"===="+item.Count);

foreach (var haha in item.Persons)

{

Console.WriteLine(haha.name);

}

}

/*

* 连接

* 一个不恰当的离子,我么现在扩张一种类,来描述动物,同样具有名字与年龄,我们用连接,

* 查询与动物相同年龄的人

*/

var query13 = GetMyAnimal().Select(animal => animal);

var query14 = GetMyList().Select(person => person);

var query15 = from per in query14

join animal in query13 on per.age equals animal.age

select new

{

DogName = animal.name,

DogAge = animal.age,

PersonName = per.name,

PersonAge = per.age

};

foreach (var v in query15)

{

Console.WriteLine("人名:{0} , 年纪{1}------动物名:{2} ,年纪{3}", v.PersonName, v.PersonAge, v.DogName, v.DogAge);

}

// 设置方法

//Concat(连接)

//说明:连接不同的集合,不会自动过滤相同项;延迟。

IEnumerable<Animal> ani = GetMyAnimal();

IEnumerable<Person> pers = GetMyList();

int i = 0;

var query16 = (from a in ani select a.name).Concat(from p in pers select p.name);

Console.WriteLine("--------------连接操作----------");

foreach (var str in query16)

{

++i;

Console.WriteLine(str);

}

Console.WriteLine("个数:" + i);

//可以看出,我们将所有人与动物的名字做了一个连接操作,全部显示了出,不过并没有自动过滤重复项目

//以上示例,只是连接了一个字段,下面我们复合型式连接

Console.WriteLine("--------------复合连接操作----------");

var query17 = (from a in ani select new { Name = a.name, Age = a.age })

.Concat(from p in pers select new { Name = p.name, Age = p.age });

i = 0;

foreach (var str in query17)

{

++i;

Console.WriteLine(str.Name + " " + str.Age);

}

Console.WriteLine("个数:" + i);

//Union(合并)

//说明:连接不同的集合,自动过滤相同项;延迟。即是将两个集合进行合并操作,过滤相同的项。

var query18 = (from a in ani select a.name).Union(from p in pers select p.name);

Console.WriteLine("--------------合并操作----------");

i = 0;

foreach (var str in query18)

{

Console.WriteLine(str);

++i;

}

Console.WriteLine("个数:" + i);

//可以看出,我们将所有人与动物的名字做了一个连接操作,全部显示了出,不过并没有自动过滤重复项目

//以上示例,只是连接了一个字段,下面我们复合型式连接

IEnumerable<Animal> ani2 = GetMyAnimal();

IEnumerable<Person> pers2 = GetMyList();

Console.WriteLine("--------------复合合并操作----------");

var query19 = (from a in ani2 select new { Age = a.age, Name = a.name })

.Union(from p in pers2 select new { Age = p.age, Name = p.name });

i = 0;

foreach (var str in query19)

{

++i;

Console.WriteLine(str.Age + " " + str.Name);

}

Console.WriteLine("个数:" + i);

//这时有一点疑问,并集比较时,没有按匿名对象,而依然是在用 name,不知道为什么

//Intersect(相交)

//说明:取相交项;延迟。即是获取不同集合的相同项(交集)。即先遍历第一个集合,找出所有唯一的元素,

//然后遍历第二个集合,并将每个元素与前面找出的元素作对比,返回所有在两个集合内都出现的元素。

Console.WriteLine("--------------相交操作----------");

var query20 = (from a in ani2 select new { Age = a.age, Name = a.name })

.Intersect(from p in pers2 select new { Age = p.age, Name = p.name });

i = 0;

foreach (var str in query20)

{

++i;

Console.WriteLine(str.Age + " " + str.Name);

}

Console.WriteLine("个数:" + i);

//  Except(与非)

//说明:排除相交项;延迟。即是从某集合中删除与另一个集合中相同的项。

//   先遍历第一个集合,找出所有唯一的元素,然后再遍历第二个集合,

//   返回第二个集合中所有未出现在前面所得元素集合中的元素。

Console.WriteLine("--------------与非操作----------");

var query21 = (from a in pers2 select new { Age = a.age, Name = a.name })

.Except(from p in ani2 select new { Age = p.age, Name = p.name });

i = 0;

foreach (var str in query21)

{

++i;

Console.WriteLine(str.Age + " " + str.Name);

}

Console.WriteLine("个数:" + i);

//分区

//扩展方法 Take与Skip等分区操作可以用于分页,例如显示5*5个人

//一页显示的条数

int pageSize = 2;

//页数计算

int numberPages = (int)Math.Ceiling(GetMyList().Count() / (double)pageSize);

for (int page = 0; page < numberPages; page++)

{

Console.WriteLine("-------------------第{0}页-------------------------------", page);

var persons = (from r in GetMyList() select r.name).Skip(page * pageSize).Take(pageSize);

foreach (var a in persons)

{

Console.WriteLine(a);

}

}

//可以看出skip是指忽略多少条,Take是指从取到的记录中取几条

//合并操作

//Count用来计算项目数,下面我们选中拥有车超过3辆的人

var query22 = from person in GetMyList() where person.list.Count() >= 2 select new { Name = person.name, Age = person.age, Count = person.list.Count() };

Console.WriteLine("-----------------------选出拥有车俩3俩以上的人------------");

foreach (var a in query22)

{

Console.WriteLine(a.Name + " " + a.Age + " " + a.Count);

}

//Sum汇总数字的合

//下面,我们用Sum求出所有人年纪的总合(按人名先分组)

Console.WriteLine("-------------------------所有人年纪的总合------------------");

var query23 = from ppp in GetMyList()

group ppp by ppp.name into g

select new

{

Name = g.Key,

AgeSum = (from p in pers select p.age).Sum(),

Count = g.Count()

};

foreach (var a in query23)

{

Console.WriteLine(a.Name + "   " + a.AgeSum + "  " + a.Count);

}

//转换

//之前我们用到的查询,都是在foreach时才会真正的执行,下面我们的方式是强制立即执行,将结果放数集合数组等容器中

List<Person> list = (from p in GetMyList() select p).ToList();

Console.WriteLine("立即执行查询-----------------------");

foreach (var a in list)

{

Console.WriteLine(a.age + a.name);

foreach (var p in a.list)

{

Console.WriteLine(p.name);

}

}

//接着,我们做一个字典,车对人(一对多)

ILookup<string, Person> per111 = (from per in GetMyList()

from c in per.list

select new

{

Car = c.name,

Person = per

}).ToLookup(p => p.Car, p => p.Person);

Console.WriteLine(per111.Count);

if (per111.Contains("奔驰"))

{

foreach (var p in per111["奔驰"])

{

Console.WriteLine("有这个车的人:{0}", p.name);

}

}

//如果要在非泛型版的集合上使用,可以用Cast方法强制得到类型

ArrayList arr = new ArrayList(GetMyList() as ICollection);//需要添加命名空间

var qqq = from a in arr.Cast<Person>() where a.name == "aladdin" select a;

//11.2.13生成操作符

// Range() Empty() Repear()不是扩展方法,而是返回序列的正常静态方法

// 在LINQ to Objects中,这些方法可以用于Enumearable类

// 有时需要填充一个范围的数字,这时需要用到Range方法,第一个参数做为起始值,第二个是指填充的项目数

var values = Enumerable.Range(1, 20).Select(n => n * 3);

foreach (var a in values)

{

Console.Write(a + " ");

}

//结果1 2 3 4 .....20

//比如某个方法,参数是一个集合,我们传一个空进去,就可以用Empty

var em = Enumerable.Empty<int>();

var pep = Enumerable.Repeat("fuck ", 10);

foreach (var a in pep)

{

Console.WriteLine(a);

}

//Repeat用于把特定元素按指定的重复次数爹代

Console.ReadKey();

}

public static void PrintMyInfo(IEnumerable<Person> en)

{

foreach (var item in en)

{

Console.WriteLine("姓名 : {0} , 年龄 : {1}", item.name, item.age);

}

}

/// <summary>

/// 得到一些Animal实例,并将这些实例存放到集合中

/// </summary>

/// <returns></returns>

public static IEnumerable<Animal> GetMyAnimal()

{

List<Animal> lists = new List<Animal>();

Animal p1 = new Animal("aladdin", 21);

Animal p2 = new Animal("apple", 22);

Animal p3 = new Animal("angel", 30);

Animal p4 = new Animal("jacky", 22);

lists.Add(p1);

lists.Add(p2);

lists.Add(p3);

lists.Add(p4);

return lists;

}

/// <summary>

/// 这是返回Person集合的方法,视同该方法得到一些Person的实例化对象

/// </summary>

/// <returns></returns>

public static IEnumerable<Person> GetMyList()

{

List<Person> lists = new List<Person>();

Person p1 = new Person("aladdin", 21);

Person p2 = new Person("apple", 22);

Person p3 = new Person("angel", 30);

Person p4 = new Person("jacky", 20);

Person p5 = new Person("zhao", 11);

Person p6 = new Person("fuck", 33);

Person p7 = new Person("emep", 25);

Person p8 = new Person("xiaoming", 88);

Person p9 = new Person("along", 88);

Person p10 = new Person("dafei", 99);

Person p11 = new Person("bige", 99);

Person p12 = new Person("feitianlong", 77);

Person p13 = new Person("dalianmao", 77);

Person p14 = new Person("guixianren", 21);

Person p15 = new Person("yuebuqun", 21);

//list是Person中的字段,该字段能存放Cars类

p1.list.Add(new Cars("奔驰"));

p1.list.Add(new Cars("宝马"));

p1.list.Add(new Cars("拖拉机"));

p2.list.Add(new Cars("自行车"));

p2.list.Add(new Cars("摩托"));

p3.list.Add(new Cars("奔驰"));

p3.list.Add(new Cars("陆虎"));

p4.list.Add(new Cars("捷达"));

p4.list.Add(new Cars("哈飞"));

p5.list.Add(new Cars("奔驰"));

p5.list.Add(new Cars("宝时捷"));

p6.list.Add(new Cars("奔驰"));

p6.list.Add(new Cars("霸道"));

p7.list.Add(new Cars("昌河"));

p7.list.Add(new Cars("长安之星"));

//将Person的每个实例添加到List<Person>中

lists.Add(p1);

lists.Add(p2);

lists.Add(p3);

lists.Add(p4);

lists.Add(p5);

lists.Add(p6);

lists.Add(p7);

lists.Add(p8);

lists.Add(p9);

lists.Add(p10);

lists.Add(p11);

lists.Add(p12);

lists.Add(p13);

lists.Add(p14);

lists.Add(p15);

return lists;

}

}

public class Person

{

public string name;

public int age;

public List<Cars> list = new List<Cars>();

public Person(string name, int age)

{

this.name = name;

this.age = age;

}

}

public class Cars

{

public string name;

public Cars(string name)

{

this.name = name;

}

}

public class Animal

{

public string name;

public int age;

public Animal(string name, int age)

{

this.name = name;

this.age = age;

}

}

}

总结:这个案例,可能你看不太懂,没关系,慢慢来,结合我的认识还有网上的,我已经尽可能的写了注释,对于初学真可能有点难度,但是会了这个案例,就差不多明白了LINQ的大部分了,剩下的就是熟练运用了.

时间: 2024-12-10 21:23:45

C#编程(六十二)---------LINQ标准的查询操作符的相关文章

C#高级编程六十二天----LINQ标准的查询操作符

LINQ标准的查询操作符 首先我们来看一下LINQ的操作符,可根据查询操作符的操作"类型"进行分类,如把它们分成投影,限制,排序,联接,分组,串联,聚合,集合,生成,转换,元素,相等,量词,分割等. 类型 操作符名称 投影操作符 Select,SelectMany 限制操作符 Where 排序操作符 OrderBy,OrderByDescending,ThenBy,ThenByDescending,Reverse 联接操作符 Join,GroupJoin 分组操作符 GroupBy 串

QT开发(六十二)———QT5解析Json文件

QT开发(六十二)---QT5解析Json文件 一.QT5 Json简介 QT4中使用第三方库QJson解析JSON文件. QT5新增加了处理JSON的类,类均以QJson开头,包含在QtCore模块中.QT5新增加六个相关类: QJsonArray 封装 JSON 数组 QJsonDocument 读写 JSON 文档 QJsonObject 封装 JSON 对象 QJsonObject::iterator 用于遍历QJsonObject的STL风格的非const遍历器 QJsonParseE

Windows界面编程第十二篇 位图显示特效 飞入效果与伸展效果

分享一下我老师大神的人工智能教程吧.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net 转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8696726 欢迎关注微博:http://weibo.com/MoreWindows Windows界面编程之位图显示特效系列目录: 1. <Windows界面编程第九篇位图显示特效交错效果> http:/

shell编程(十二)--- 添加用户示例

[[email protected] Learn]# cat useradd-final.sh  #!/bin/bash # DEBUG=0 ADD=0 DEL=0 help() { echo "Usage: $(basename $0) -v | --verbose | --add user1,user2,... | --del user1,user2,... | -h | --help" } while [ $# -ne 0 ] do case $1 in -h | --help 

Linux系统裁剪之二(Bash脚本编程之十二)

Linux系统裁剪之二(Bash脚本编程之十二) 系统函数库 ·Linux系统的启动流程     1,POST(加电自检) 计算机本身并不会执行程序,它只是一堆破铜烂铁,但是它可以在开机的时候先去载入一段程序,系统在刚刚启动的时候能够实现将某个ROM芯片中的程序映射到CPU能够寻址的地址空间中去,并且让CPU能够执行其中的指令,这些指令大部分都是用来做系统检测的,当检测完成后,如果系统中所有的基本硬件和核心硬件都没有问题的话,接下来就会根据BIOS中设定的系统启动次序(Boot Sequence

Gradle 1.12用户指南翻译——第二十二章. 标准的 Gradle 插件

其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/userguide/userguide.html. 另外,Android 手机用户可通过我写的一个程序浏览文档,带缓存功能的,兼容

C#高级编程六十七天----LINQ提供程序

LINQ提供程序 .NET3.5包含了几个LINQ提供程序. LINQ提供程序为特定的数据源实现了标准的查询操作符. LINQ提供程序也许会实现LINQ定义的更多扩展方法,但至少要实现标准操作符. LINQ to XML 不仅实现了专门用于XML 的方法,还实现了其他方法,例如System.Xml.Linq 命名空间的Extensions类定义的方法Elements(),Descendants 和Ancestors. LINQ提供程序的实现方案是根据命名空间和第一个参数的类型来实现的. 实现扩展

对于未来编程的十二种预测

凝视水晶球,我们试图寻找未来五年中关于编程会发生什么,哪些会激动人心. 技术领域快速变革着,而用于构建这些技术的工具也随之不断发展.如果你不能超越当前的项目,那你就只能在兔子洞里越陷越深了. 为了帮助您呈现一个精彩的未来,我们预测了未来五年内编程领域将进行的颠覆性变革.由于我们的水晶球的主观色彩很浓,以下这些猜想也许并不是普遍适用的,还有一些或许在五年内不能完全实现.有些虽然已成为了现实,但真理的确立不是一蹴而就的. 亲爱的读者,请你快速阅读吧,因为未来将以超越我们认知的速度发展着. 1. GP

java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessController的checkPerssiom方法,访问控制器AccessController的栈检查机制又遍历整个 PerssiomCollection来判断具体拥有什么权限一旦发现栈中一个权限不允许的时候抛出异常否则简单的返回,这个过程实际上比我的描述要复杂 得多,这里我只是简单的一句带过,因为这