Creating and Populating a Wrapper in Apex

As Apex is a statically typed language, you must choose only one object type per list to iterate.
What if you want to iterate an object which can contain multiple standard and custom objects inside it?
You would need to wrap those objects collectively in a class type which is called wrapper class.
MyWrapper is the wrapper class which is also an inner class of CustomWrapperController and contains two member variables of type Contact and Opportunity.
We are populating data in member class variable of the Outer class inside its constructor and we can use the same List type member variable in Vf page or Lightning Component to display the data in visually attractive form.
The below example has a wrapper class which includes two objects Contact and Opportunity :

public with sharing class CustomWrapperController {    
    public class MyWrapper{
        public Contact con { get ; private set;}
        public Opportunity opp { get ; private set;}       
        public MyWrapper(Contact c,Opportunity o){
            this.con = c;
            this.opp = o;
    public List<MyWrapper> wrapperList { get ; private set;}    
    public CustomWrapperController(){       
        Map<Id,Contact> conMap = new Map<Id,Contact>([SELECT Id,Name from Contact where Id IN
                  (SELECT ContactId from OpportunityContactRole Where isPrimary=true)]);        
        Map<Id,Opportunity> oppMap = new Map<Id,Opportunity>([SELECT Id,Name from Opportunity where Id IN
                  (SELECT OpportunityId from OpportunityContactRole Where isPrimary=true)]);        
        List<OpportunityContactRole> oppConRoles = [SELECT OpportunityId,ContactId from OpportunityContactRole 
                                                   where isPrimary=true];
        this.wrapperList = new List<MyWrapper>();
        for(OpportunityContactRole ocr : oppConRoles){
            this.wrapperList.add(new MyWrapper(conMap.get(ocr.ContactId),oppMap.get(ocr.OpportunityId)));